diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2026-01-02 17:10:21 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2026-01-09 12:51:45 +0000 |
| commit | 4b9e0bf8cad5aba3bbba29c7abd9fb1b643eea02 (patch) | |
| tree | af3aba7be289043cfbd8602fdfd7ce4d7cf57187 /pkg/aflow | |
| parent | 963dd62f086e3885f11dd3700ef3cc56df2659e2 (diff) | |
pkg/aflow/flow/patching: add bug fix patching workflow
Diffstat (limited to 'pkg/aflow')
| -rw-r--r-- | pkg/aflow/flow/patching/base_commit.go | 57 | ||||
| -rw-r--r-- | pkg/aflow/flow/patching/patching.go | 138 |
2 files changed, 195 insertions, 0 deletions
diff --git a/pkg/aflow/flow/patching/base_commit.go b/pkg/aflow/flow/patching/base_commit.go new file mode 100644 index 000000000..f49aba3d6 --- /dev/null +++ b/pkg/aflow/flow/patching/base_commit.go @@ -0,0 +1,57 @@ +// Copyright 2025 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 patching + +import ( + "github.com/google/syzkaller/pkg/aflow" + "github.com/google/syzkaller/pkg/aflow/action/kernel" + "github.com/google/syzkaller/pkg/vcs" +) + +var baseCommitPicker = aflow.NewFuncAction("base-commit-picker", pickBaseCommit) + +type baseCommitArgs struct { + // Can be used to override the selected base commit (for manual testing). + FixedBaseCommit string +} + +type baseCommitResult struct { + KernelRepo string + KernelCommit string +} + +func pickBaseCommit(ctx *aflow.Context, args baseCommitArgs) (baseCommitResult, error) { + // Currently we use the latest RC of the mainline tree as the base. + // This is a reasonable choice overall in lots of cases, and it enables good caching + // of all artifacts (we need to rebuild them only approx every week). + // Potentially we can use subsystem trees for few important, well-maintained subsystems + // (mm, net, etc). However, it will work poorly for all subsystems. First, there is no + // machine-usable mapping of subsystems to repo/branch; second, lots of them are poorly + // maintained (can be much older than latest RC); third, it will make artifact caching + // much worse. + // In the future we ought to support automated rebasing of patches to requested trees/commits. + // We need it anyway, but it will also alleviate imperfect base commit picking. + const ( + baseRepo = "git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git" + baseBranch = "master" + ) + + res := baseCommitResult{ + KernelRepo: baseRepo, + KernelCommit: args.FixedBaseCommit, + } + if args.FixedBaseCommit != "" { + return res, nil + } + + err := kernel.UseLinuxRepo(ctx, func(_ string, repo vcs.Repo) error { + head, err := repo.Poll(baseRepo, baseBranch) + if err != nil { + return err + } + res.KernelCommit, err = repo.ReleaseTag(head.Hash) + return err + }) + return res, err +} diff --git a/pkg/aflow/flow/patching/patching.go b/pkg/aflow/flow/patching/patching.go new file mode 100644 index 000000000..ef10f1a2e --- /dev/null +++ b/pkg/aflow/flow/patching/patching.go @@ -0,0 +1,138 @@ +// Copyright 2025 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 patching + +import ( + "encoding/json" + + "github.com/google/syzkaller/pkg/aflow" + "github.com/google/syzkaller/pkg/aflow/action/crash" + "github.com/google/syzkaller/pkg/aflow/action/kernel" + "github.com/google/syzkaller/pkg/aflow/ai" + "github.com/google/syzkaller/pkg/aflow/tool/codesearcher" +) + +type Inputs struct { + ReproOpts string + ReproSyz string + ReproC string + KernelConfig string + SyzkallerCommit string + CodesearchToolBin string + + // Same as in the manager config. + Syzkaller string + Image string + Type string + VM json.RawMessage + + // Use this fixed based kernel commit (for testing/local running). + FixedBaseCommit string +} + +type Outputs struct { + PatchDescription string + PatchDiff string +} + +func init() { + tools := codesearcher.Tools + + aflow.Register[Inputs, Outputs]( + ai.WorkflowPatching, + "generate a kernel patch fixing a provided bug reproducer", + &aflow.Flow{ + Root: &aflow.Pipeline{ + Actions: []aflow.Action{ + baseCommitPicker, + kernel.Checkout, + kernel.Build, + // Ensure we can reproduce the crash (and the build boots). + crash.Reproduce, + codesearcher.PrepareIndex, + &aflow.LLMAgent{ + Name: "debugger", + Reply: "BugExplanation", + Temperature: 1, + Instruction: debuggingInstruction, + Prompt: debuggingPrompt, + Tools: tools, + }, + &aflow.LLMAgent{ + Name: "diff-generator", + Reply: "PatchDiff", + Temperature: 1, + Instruction: diffInstruction, + Prompt: diffPrompt, + Tools: tools, + }, + &aflow.LLMAgent{ + Name: "description-generator", + Reply: "PatchDescription", + Temperature: 1, + Instruction: descriptionInstruction, + Prompt: descriptionPrompt, + }, + }, + }, + }, + ) +} + +// TODO: mention not doing assumptions about the source code, and instead querying code using tools. +// TODO: mention to extensively use provided tools to confirm everything. +// TODO: use cause bisection info, if available. + +const debuggingInstruction = ` +You are an experienced Linux kernel developer tasked with debugging a kernel crash root cause. +You need to provide a detailed explanation of the root cause for another developer to be +able to write a fix for the bug based on your explanation. +Your final reply must contain only the explanation. + +Call some codesearch tools first. +` + +const debuggingPrompt = ` +The crash is: + +{{.CrashReport}} +` + +const diffInstruction = ` +You are an experienced Linux kernel developer tasked with creating a patch for a kernel bug. +Your final reply should contain only the code diff in patch format. +` + +const diffPrompt = ` +The crash that corresponds to the bug is: + +{{.CrashReport}} + +The explanation of the root cause of the bug is: + +{{.BugExplanation}} +` + +const descriptionInstruction = ` +You are an experienced Linux kernel developer tasked with writing a commit description for +a kernel bug fixing commit. The description should start with a one-line summary, +and then include description of the bug being fixed, and how it's fixed by the provided patch. +Your final reply should contain only the text of the commit description. +Phrase the one-line summary so that it is not longer than 72 characters. +The rest of the description must be word-wrapped at 72 characters. +` + +const descriptionPrompt = ` +The crash that corresponds to the bug is: + +{{.CrashReport}} + +The explanation of the root cause of the bug is: + +{{.BugExplanation}} + +The diff of the bug fix is: + +{{.PatchDiff}} +` |
