aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2026-01-02 17:10:21 +0100
committerDmitry Vyukov <dvyukov@google.com>2026-01-09 12:51:45 +0000
commit4b9e0bf8cad5aba3bbba29c7abd9fb1b643eea02 (patch)
treeaf3aba7be289043cfbd8602fdfd7ce4d7cf57187 /pkg
parent963dd62f086e3885f11dd3700ef3cc56df2659e2 (diff)
pkg/aflow/flow/patching: add bug fix patching workflow
Diffstat (limited to 'pkg')
-rw-r--r--pkg/aflow/flow/patching/base_commit.go57
-rw-r--r--pkg/aflow/flow/patching/patching.go138
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}}
+`