diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2025-08-19 12:09:14 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-08-19 15:02:37 +0000 |
| commit | 8c32f0ff1ce7f5076910229181d6f43a194531e4 (patch) | |
| tree | f5c43e76dc546d14995c0254d9690960d3fb3a73 /syz-cluster | |
| parent | 0773c4252b9eda702503351c75aca73526a13b6c (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.go | 1 | ||||
| -rw-r--r-- | syz-cluster/pkg/db/migrations/5_session_test_skipped.down.sql | 3 | ||||
| -rw-r--r-- | syz-cluster/pkg/db/migrations/5_session_test_skipped.up.sql | 3 | ||||
| -rw-r--r-- | syz-cluster/workflow/fuzz-step/main.go | 28 | ||||
| -rw-r--r-- | syz-cluster/workflow/fuzz-step/main_test.go | 20 |
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"}, + )) + }) +} |
