aboutsummaryrefslogtreecommitdiffstats
path: root/syz-cluster
diff options
context:
space:
mode:
authorAleksandr Nogikh <nogikh@google.com>2025-08-19 12:09:14 +0200
committerAleksandr Nogikh <nogikh@google.com>2025-08-19 15:02:37 +0000
commit8c32f0ff1ce7f5076910229181d6f43a194531e4 (patch)
treef5c43e76dc546d14995c0254d9690960d3fb3a73 /syz-cluster
parent0773c4252b9eda702503351c75aca73526a13b6c (diff)
syz-cluster: skip fuzzing if binaries are the same
If all symbol hashes between the base and the pathed kernel match, there's no reason to spend time fuzzing the series. Add a 'skipped' status to the enum of possible session test results and set it from the fuzz-step.
Diffstat (limited to 'syz-cluster')
-rw-r--r--syz-cluster/pkg/api/api.go1
-rw-r--r--syz-cluster/pkg/db/migrations/5_session_test_skipped.down.sql3
-rw-r--r--syz-cluster/pkg/db/migrations/5_session_test_skipped.up.sql3
-rw-r--r--syz-cluster/workflow/fuzz-step/main.go28
-rw-r--r--syz-cluster/workflow/fuzz-step/main_test.go20
5 files changed, 54 insertions, 1 deletions
diff --git a/syz-cluster/pkg/api/api.go b/syz-cluster/pkg/api/api.go
index 60c106254..65f0f4bd2 100644
--- a/syz-cluster/pkg/api/api.go
+++ b/syz-cluster/pkg/api/api.go
@@ -73,6 +73,7 @@ type Build struct {
const (
TestRunning string = "running"
TestPassed string = "passed"
+ TestSkipped string = "skipped"
TestFailed string = "failed" // TODO: drop it? only mark completion?
TestError string = "error"
)
diff --git a/syz-cluster/pkg/db/migrations/5_session_test_skipped.down.sql b/syz-cluster/pkg/db/migrations/5_session_test_skipped.down.sql
new file mode 100644
index 000000000..dbda912f2
--- /dev/null
+++ b/syz-cluster/pkg/db/migrations/5_session_test_skipped.down.sql
@@ -0,0 +1,3 @@
+ALTER TABLE SessionTests DROP CONSTRAINT ResultEnum;
+ALTER TABLE SessionTests ADD CONSTRAINT ResultEnum CHECK (Result IN ('passed', 'failed', 'error', 'running'));
+DROP INDEX SessionTestsByResult;
diff --git a/syz-cluster/pkg/db/migrations/5_session_test_skipped.up.sql b/syz-cluster/pkg/db/migrations/5_session_test_skipped.up.sql
new file mode 100644
index 000000000..8509fd816
--- /dev/null
+++ b/syz-cluster/pkg/db/migrations/5_session_test_skipped.up.sql
@@ -0,0 +1,3 @@
+ALTER TABLE SessionTests DROP CONSTRAINT ResultEnum;
+ALTER TABLE SessionTests ADD CONSTRAINT ResultEnum CHECK (Result IN ('passed', 'failed', 'error', 'running', 'skipped'));
+CREATE INDEX SessionTestsByResult ON SessionTests(SessionID, Result);
diff --git a/syz-cluster/workflow/fuzz-step/main.go b/syz-cluster/workflow/fuzz-step/main.go
index 77432ec4f..954c9d25c 100644
--- a/syz-cluster/workflow/fuzz-step/main.go
+++ b/syz-cluster/workflow/fuzz-step/main.go
@@ -68,7 +68,9 @@ func main() {
defer cancel()
err = run(runCtx, client, d, store)
status := api.TestPassed // TODO: what about TestFailed?
- if err != nil && !errors.Is(err, context.DeadlineExceeded) {
+ if errors.Is(err, errSkipFuzzing) {
+ status = api.TestSkipped
+ } else if err != nil && !errors.Is(err, context.DeadlineExceeded) {
app.Errorf("the step failed: %v", err)
status = api.TestError
}
@@ -79,6 +81,8 @@ func main() {
}
}
+var errSkipFuzzing = errors.New("skip")
+
func run(baseCtx context.Context, client *api.Client, timeout time.Duration,
store *manager.DiffFuzzerStore) error {
series, err := client.GetSessionSeries(baseCtx, *flagSession)
@@ -100,6 +104,10 @@ func run(baseCtx context.Context, client *api.Client, timeout time.Duration,
if err != nil {
app.Errorf("failed to read symbol hashes: %v", err)
}
+
+ if shouldSkipFuzzing(baseSymbols, patchedSymbols) {
+ return errSkipFuzzing
+ }
manager.PatchFocusAreas(patched, series.PatchBodies(), baseSymbols, patchedSymbols)
if *flagCorpusURL != "" {
@@ -288,6 +296,24 @@ func reportFinding(ctx context.Context, client *api.Client, bug *manager.UniqueB
return client.UploadFinding(ctx, finding)
}
+func shouldSkipFuzzing(baseSymbols, patchedSymbols map[string]string) bool {
+ if len(baseSymbols) == 0 || len(patchedSymbols) == 0 {
+ // Likely, something went wrong during the kernel build step.
+ log.Logf(0, "skipped the binary equality check because some of them have 0 symbols")
+ return false
+ }
+ if len(baseSymbols) == len(patchedSymbols) {
+ for name, hash := range baseSymbols {
+ if patchedSymbols[name] != hash {
+ log.Logf(0, "binaries are different, continuing fuzzing")
+ return false
+ }
+ }
+ }
+ log.Logf(0, "binaries are the same, no sense to do fuzzing")
+ return true
+}
+
func readSymbolHashes() (base, patched map[string]string, err error) {
// These are saved by the build step.
base, err = readJSONMap("/base/symbol_hashes.json")
diff --git a/syz-cluster/workflow/fuzz-step/main_test.go b/syz-cluster/workflow/fuzz-step/main_test.go
index fa339f451..49ec3b330 100644
--- a/syz-cluster/workflow/fuzz-step/main_test.go
+++ b/syz-cluster/workflow/fuzz-step/main_test.go
@@ -7,6 +7,8 @@ import (
"io/fs"
"path/filepath"
"testing"
+
+ "github.com/stretchr/testify/assert"
)
func TestConfigLoad(t *testing.T) {
@@ -26,3 +28,21 @@ func TestConfigLoad(t *testing.T) {
return nil
})
}
+
+func TestShouldSkipFuzzing(t *testing.T) {
+ t.Run("one empty", func(t *testing.T) {
+ assert.False(t, shouldSkipFuzzing(nil, map[string]string{"A": "1"}))
+ })
+ t.Run("equal", func(t *testing.T) {
+ assert.True(t, shouldSkipFuzzing(
+ map[string]string{"A": "1", "B": "2"},
+ map[string]string{"A": "1", "B": "2"},
+ ))
+ })
+ t.Run("different", func(t *testing.T) {
+ assert.False(t, shouldSkipFuzzing(
+ map[string]string{"A": "1", "B": "2"},
+ map[string]string{"A": "1", "B": "different"},
+ ))
+ })
+}