diff options
Diffstat (limited to 'pkg/aflow/flow/assessment/moderation.go')
| -rw-r--r-- | pkg/aflow/flow/assessment/moderation.go | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/pkg/aflow/flow/assessment/moderation.go b/pkg/aflow/flow/assessment/moderation.go new file mode 100644 index 000000000..4b78f901c --- /dev/null +++ b/pkg/aflow/flow/assessment/moderation.go @@ -0,0 +1,114 @@ +// Copyright 2026 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package assessmenet + +import ( + "fmt" + + "github.com/google/syzkaller/pkg/aflow" + "github.com/google/syzkaller/pkg/aflow/action/kernel" + "github.com/google/syzkaller/pkg/aflow/ai" + "github.com/google/syzkaller/pkg/aflow/tool/codesearcher" + "github.com/google/syzkaller/pkg/report/crash" +) + +type moderationInputs struct { + BugTitle string + CrashReport string + KernelRepo string + KernelCommit string + KernelConfig string + CodesearchToolBin string +} + +type moderationOutputs struct { + Confident bool + Actionable bool + Explanation string +} + +func init() { + aflow.Register[moderationInputs, moderationOutputs]( + ai.WorkflowModeration, + "assess if a bug report is consistent and actionable or not", + &aflow.Flow{ + Root: &aflow.Pipeline{ + Actions: []aflow.Action{ + aflow.NewFuncAction("extract-crash-type", extractCrashType), + kernel.Checkout, + kernel.Build, + codesearcher.PrepareIndex, + &aflow.LLMAgent{ + Name: "expert", + Reply: "Explanation", + Outputs: aflow.LLMOutputs[struct { + Confident bool `jsonschema:"If you are confident in the verdict of the analysis or not."` + Actionable bool `jsonschema:"If the report is actionable or not."` + }](), + Temperature: 1, + Instruction: moderationInstruction, + Prompt: moderationPrompt, + Tools: codesearcher.Tools, + }, + }, + }, + }, + ) +} + +const moderationInstruction = ` +You are an experienced Linux kernel developer tasked with determining if the given kernel bug +report is actionable or not. Actionable means that it contains enough info to root cause +the underlying bug, and that the report is self-consistent and makes sense, rather than +e.g. a one-off nonsensical crash induced by a previous memory corruption. + +{{if .IsUAF}} +The bug report is about a use-after-free bug generated by KASAN tool. +It should contain 3 stack traces: the bad memory access stack, the heap block allocation stack, +and the heap block free stack. If the report does not contain 3 stacks, it's not actionable. + +All 3 stack traces should be related to the same object type, +and usually be in the same kernel subsystem (at least leaf stack frames). +An example of an actionable and consistent report would be: first access stack relates +to an access to a field of struct Foo, allocation/free stacks relate to allocation/free +of the struct Foo. +In inconsistent/nonsensical reports an access may be to a struct Foo, but allocation +stack allocates a different structure in a different subsystem. +Look for other suspicious signals/inconsistencies that can make this report hard to +debug/understand. +{{end}} + +In the final reply explain why you think the report is self-consistent and actionable, +or why it's inconsistent and/or not actionable. + +Use the provided tools to confirm any assumptions, variables/fields being accessed, etc. +In particular, don't make assumptions about the kernel source code, +use codesearch tools to read the actual source code. +` + +const moderationPrompt = ` +The bug report is: + +{{.CrashReport}} +` + +type extractArgs struct { + BugTitle string +} + +type extractResult struct { + IsUAF bool +} + +func extractCrashType(ctx *aflow.Context, args extractArgs) (extractResult, error) { + var res extractResult + typ := crash.TitleToType(args.BugTitle) + switch { + case typ.IsUAF(): + res.IsUAF = true + default: + return res, fmt.Errorf("unsupported bug type") + } + return res, nil +} |
