aboutsummaryrefslogtreecommitdiffstats
path: root/syz-cluster
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2026-01-08 13:49:39 +0100
committerAleksandr Nogikh <nogikh@google.com>2026-01-09 14:28:59 +0000
commit96e9343c651cbec29d24b687b6f77a3226a6c1a1 (patch)
tree40242f4a72e952eaa25b8c8cd809be743d11a470 /syz-cluster
parent993a1e9ee26349d7e290ca7de23faeb6781d9001 (diff)
syz-cluster: guess base patch by blob hashes from the diff
Before traversing the list of trees, attempt to determine the base tree/commit by looking at the SHA hashes from the supplied git diffs.
Diffstat (limited to 'syz-cluster')
-rw-r--r--syz-cluster/pkg/triage/commit.go3
-rw-r--r--syz-cluster/pkg/triage/git.go5
-rw-r--r--syz-cluster/pkg/triage/tree.go9
-rw-r--r--syz-cluster/pkg/triage/tree_test.go6
-rw-r--r--syz-cluster/workflow/triage-step/main.go97
5 files changed, 99 insertions, 21 deletions
diff --git a/syz-cluster/pkg/triage/commit.go b/syz-cluster/pkg/triage/commit.go
index 81c7f6150..53229e32c 100644
--- a/syz-cluster/pkg/triage/commit.go
+++ b/syz-cluster/pkg/triage/commit.go
@@ -12,8 +12,7 @@ import (
)
// TODO: Some further improvements:
-// 1. Consider the blob hashes incorporated into the git diff. These may restrict the set of base commits.
-// 2. Add support for experimental sessions: these may be way behind the current HEAD.
+// 1. Add support for experimental sessions: these may be way behind the current HEAD.
type TreeOps interface {
HeadCommit(tree *api.Tree) (*vcs.Commit, error)
diff --git a/syz-cluster/pkg/triage/git.go b/syz-cluster/pkg/triage/git.go
index 390bd11b1..58437c913 100644
--- a/syz-cluster/pkg/triage/git.go
+++ b/syz-cluster/pkg/triage/git.go
@@ -7,6 +7,7 @@ import (
"fmt"
"os"
+ "github.com/google/syzkaller/pkg/debugtracer"
"github.com/google/syzkaller/pkg/vcs"
"github.com/google/syzkaller/syz-cluster/pkg/api"
)
@@ -55,3 +56,7 @@ func (ops *GitTreeOps) ApplySeries(commit string, patches [][]byte) error {
}
return nil
}
+
+func (ops *GitTreeOps) BaseForDiff(patch []byte, tracer debugtracer.DebugTracer) (*vcs.BaseCommit, error) {
+ return ops.Git.BaseForDiff(patch, tracer)
+}
diff --git a/syz-cluster/pkg/triage/tree.go b/syz-cluster/pkg/triage/tree.go
index 6cd920429..5d75c380a 100644
--- a/syz-cluster/pkg/triage/tree.go
+++ b/syz-cluster/pkg/triage/tree.go
@@ -45,3 +45,12 @@ func SelectTrees(series *api.Series, trees []*api.Tree) []*api.Tree {
})
return result
}
+
+func TreeFromBranch(trees []*api.Tree, branch string) *api.Tree {
+ for _, tree := range trees {
+ if strings.HasPrefix(branch, tree.Name+"/") {
+ return tree
+ }
+ }
+ return nil
+}
diff --git a/syz-cluster/pkg/triage/tree_test.go b/syz-cluster/pkg/triage/tree_test.go
index 7bd9ed3ed..92d3ce014 100644
--- a/syz-cluster/pkg/triage/tree_test.go
+++ b/syz-cluster/pkg/triage/tree_test.go
@@ -74,3 +74,9 @@ func TestSelectTrees(t *testing.T) {
})
}
}
+
+func TestTreeFromBranch(t *testing.T) {
+ treeA, treeB := &api.Tree{Name: "a"}, &api.Tree{Name: "b"}
+ assert.Equal(t, treeA, TreeFromBranch([]*api.Tree{treeA, treeB}, "a/some_branch"))
+ assert.Equal(t, treeB, TreeFromBranch([]*api.Tree{treeA, treeB}, "b/some_branch"))
+}
diff --git a/syz-cluster/workflow/triage-step/main.go b/syz-cluster/workflow/triage-step/main.go
index 37eddd5e8..ff2b51d26 100644
--- a/syz-cluster/workflow/triage-step/main.go
+++ b/syz-cluster/workflow/triage-step/main.go
@@ -66,7 +66,7 @@ func main() {
type seriesTriager struct {
debugtracer.DebugTracer
client *api.Client
- ops triage.TreeOps
+ ops *triage.GitTreeOps
}
func (triager *seriesTriager) GetVerdict(ctx context.Context, sessionID string) (*api.TriageResult, error) {
@@ -112,12 +112,80 @@ func (triager *seriesTriager) GetVerdict(ctx context.Context, sessionID string)
func (triager *seriesTriager) prepareFuzzingTask(ctx context.Context, series *api.Series, trees []*api.Tree,
target *triage.MergedFuzzConfig) (*api.FuzzTask, error) {
- var skipErr error
+ result, err := triager.selectFromBlobs(series, trees)
+ if err != nil {
+ return nil, fmt.Errorf("selection by blob failed: %w", err)
+ }
+ if result == nil {
+ result, err = triager.selectFromList(ctx, series, trees, target)
+ if err != nil {
+ return nil, fmt.Errorf("selection from the list failed: %w", err)
+ }
+ }
+ if result != nil {
+ triager.Log("continuing with %+v", result)
+ base := api.BuildRequest{
+ TreeName: result.Tree.Name,
+ TreeURL: result.Tree.URL,
+ ConfigName: target.KernelConfig,
+ CommitHash: result.Commit,
+ Arch: result.Arch,
+ }
+ fuzz := &api.FuzzTask{
+ Base: base,
+ Patched: base,
+ FuzzConfig: *target.FuzzConfig,
+ }
+ fuzz.Patched.SeriesID = series.ID
+ return fuzz, nil
+ }
+ return nil, SkipError("no base commit found")
+}
+
+type SelectResult struct {
+ Tree *api.Tree
+ Commit string
+ Arch string
+}
+
+// For now, only amd64 fuzzing is supported.
+const fuzzArch = "amd64"
+
+func (triager *seriesTriager) selectFromBlobs(series *api.Series, trees []*api.Tree) (*SelectResult, error) {
+ triager.Log("attempting to guess the base commit by blob hashes")
+ var diff []byte
+ for _, patch := range series.Patches {
+ diff = append(diff, patch.Body...)
+ diff = append(diff, '\n')
+ }
+ base, err := triager.ops.BaseForDiff(diff, triager.DebugTracer)
+ if err != nil {
+ return nil, err
+ } else if base == nil {
+ triager.Log("no candidate base commit is found")
+ return nil, nil
+ }
+ for _, branch := range base.Branches {
+ tree := triage.TreeFromBranch(trees, branch)
+ if tree != nil {
+ return &SelectResult{
+ Tree: tree,
+ Commit: base.Hash,
+ Arch: fuzzArch,
+ }, nil
+ }
+ }
+ triager.Log("cannot identify the tree from %q", base.Branches)
+ return nil, nil
+}
+
+func (triager *seriesTriager) selectFromList(ctx context.Context, series *api.Series, trees []*api.Tree,
+ target *triage.MergedFuzzConfig) (*SelectResult, error) {
+ skipErr := SkipError("empty tree list")
for _, tree := range trees {
triager.Log("considering tree %q", tree.Name)
- arch := "amd64"
lastBuild, err := triager.client.LastBuild(ctx, &api.LastBuildReq{
- Arch: arch,
+ Arch: fuzzArch,
ConfigName: target.KernelConfig,
TreeName: tree.Name,
Status: api.BuildSuccess,
@@ -140,21 +208,12 @@ func (triager *seriesTriager) prepareFuzzingTask(ctx context.Context, series *ap
triager.Log("failed to find a base commit for %q", tree.Name)
continue
}
- triager.Log("selected base commit: %s", result.Commit)
- base := api.BuildRequest{
- TreeName: tree.Name,
- TreeURL: tree.URL,
- ConfigName: target.KernelConfig,
- CommitHash: result.Commit,
- Arch: arch,
- }
- fuzz := &api.FuzzTask{
- Base: base,
- Patched: base,
- FuzzConfig: *target.FuzzConfig,
- }
- fuzz.Patched.SeriesID = series.ID
- return fuzz, nil
+ triager.Log("result: %s", result.Commit)
+ return &SelectResult{
+ Tree: tree,
+ Commit: result.Commit,
+ Arch: fuzzArch,
+ }, nil
}
return nil, skipErr
}