diff options
| author | Aleksandr Nogikh <nogikh@google.com> | 2025-09-03 20:07:34 +0200 |
|---|---|---|
| committer | Aleksandr Nogikh <nogikh@google.com> | 2025-10-01 20:14:51 +0000 |
| commit | a90d2b19fb0b8b7526a51b8bbeb9b887b84503e6 (patch) | |
| tree | 300c974e4a6dcc5f07ed429f65b196469496db40 /syz-cluster | |
| parent | 9a988f5c94cd83b07d5b39f6c1225333c0715d8d (diff) | |
syz-cluster: pass fuzz config to the fuzz step as json
Instead of passing the values individually, save the FuzzConfig object
as JSON and pass it as an artifact. This will simplify adding more new
fields.
Diffstat (limited to 'syz-cluster')
| -rw-r--r-- | syz-cluster/pkg/workflow/template.yaml | 30 | ||||
| -rw-r--r-- | syz-cluster/workflow/fuzz-step/main.go | 51 | ||||
| -rw-r--r-- | syz-cluster/workflow/fuzz-step/workflow-template.yaml | 12 |
3 files changed, 52 insertions, 41 deletions
diff --git a/syz-cluster/pkg/workflow/template.yaml b/syz-cluster/pkg/workflow/template.yaml index 515adbd68..c253187e4 100644 --- a/syz-cluster/pkg/workflow/template.yaml +++ b/syz-cluster/pkg/workflow/template.yaml @@ -54,7 +54,7 @@ spec: - name: element steps: - - name: save-base-req - template: extract-request + template: convert-artifact arguments: parameters: - name: data @@ -71,12 +71,12 @@ spec: value: "{{workflow.parameters.session-id}}" artifacts: - name: request - from: "{{steps.save-base-req.outputs.artifacts.request}}" + from: "{{steps.save-base-req.outputs.artifacts.artifact}}" - - name: abort-if-base-build-failed template: exit-workflow when: "{{=jsonpath(steps['base-build'].outputs.parameters.result, '$.success') == false}}" - - name: save-patched-req - template: extract-request + template: convert-artifact arguments: parameters: - name: data @@ -113,7 +113,7 @@ spec: value: "{{workflow.parameters.session-id}}" artifacts: - name: request - from: "{{steps.save-patched-req.outputs.artifacts.request}}" + from: "{{steps.save-patched-req.outputs.artifacts.artifact}}" - - name: abort-if-patched-build-failed template: exit-workflow when: "{{=jsonpath(steps['patched-build'].outputs.parameters.result, '$.success') == false}}" @@ -137,39 +137,41 @@ spec: - - name: abort-if-patched-boot-failed template: exit-workflow when: "{{=jsonpath(steps['boot-test-patched'].outputs.parameters.result, '$.success') == false}}" + - - name: save-fuzz-config + template: convert-artifact + arguments: + parameters: + - name: data + value: "{{=jsonpath(inputs.parameters.element, '$')}}" - - name: fuzz templateRef: name: fuzz-step-template template: fuzz-step arguments: parameters: - - name: config - value: "{{=jsonpath(inputs.parameters.element, '$.config')}}" - name: patched-build-id value: "{{=jsonpath(steps['patched-build'].outputs.parameters.result, '$.build_id')}}" - name: base-build-id value: "{{=jsonpath(steps['base-build'].outputs.parameters.result, '$.build_id')}}" - - name: corpus-url - value: "{{=jsonpath(inputs.parameters.element, '$.corpus_url')}}" - - name: skip-cover-check - value: "{{=jsonpath(inputs.parameters.element, '$.skip_cover_check')}}" artifacts: - name: base-kernel from: "{{steps.base-build.outputs.artifacts.kernel}}" - name: patched-kernel from: "{{steps.patched-build.outputs.artifacts.kernel}}" - - name: extract-request + - name: config + from: "{{steps.save-fuzz-config.outputs.artifacts.artifact}}" + - name: convert-artifact inputs: parameters: - name: data outputs: artifacts: - - name: request - path: /tmp/request.json + - name: artifact + path: /tmp/artifact container: image: alpine:latest command: [sh, -c] - args: ["echo '{{inputs.parameters.data}}' > /tmp/request.json"] + args: ["echo '{{inputs.parameters.data}}' > /tmp/artifact"] - name: exit-workflow inputs: parameters: diff --git a/syz-cluster/workflow/fuzz-step/main.go b/syz-cluster/workflow/fuzz-step/main.go index 8704d1d73..fa690dc93 100644 --- a/syz-cluster/workflow/fuzz-step/main.go +++ b/syz-cluster/workflow/fuzz-step/main.go @@ -29,14 +29,12 @@ import ( ) var ( - flagConfig = flag.String("config", "", "syzkaller config") - flagSession = flag.String("session", "", "session ID") - flagBaseBuild = flag.String("base_build", "", "base build ID") - flagPatchedBuild = flag.String("patched_build", "", "patched build ID") - flagTime = flag.String("time", "1h", "how long to fuzz") - flagWorkdir = flag.String("workdir", "/workdir", "base workdir path") - flagCorpusURL = flag.String("corpus_url", "", "an URL to download corpus from") - flagSkipCoverCheck = flag.Bool("skip_cover_check", false, "don't check whether we reached the patched code") + flagConfig = flag.String("config", "", "path to the fuzz config") + flagSession = flag.String("session", "", "session ID") + flagBaseBuild = flag.String("base_build", "", "base build ID") + flagPatchedBuild = flag.String("patched_build", "", "patched build ID") + flagTime = flag.String("time", "1h", "how long to fuzz") + flagWorkdir = flag.String("workdir", "/workdir", "base workdir path") ) const testName = "Fuzzing" @@ -54,6 +52,8 @@ func main() { if !prog.GitRevisionKnown() { log.Fatalf("the binary is built without the git revision information") } + + config := readFuzzConfig() ctx := context.Background() if err := reportStatus(ctx, client, api.TestRunning, nil); err != nil { app.Fatalf("failed to report the test: %v", err) @@ -67,7 +67,7 @@ func main() { // the final test result back. runCtx, cancel := context.WithTimeout(context.Background(), d) defer cancel() - err = run(runCtx, client, d, store) + err = run(runCtx, config, client, d, store) status := api.TestPassed // TODO: what about TestFailed? if errors.Is(err, errSkipFuzzing) { status = api.TestSkipped @@ -82,6 +82,21 @@ func main() { } } +func readFuzzConfig() *api.FuzzConfig { + raw, err := os.ReadFile(*flagConfig) + if err != nil { + app.Fatalf("failed to read config: %v", err) + return nil + } + var req api.FuzzConfig + err = json.Unmarshal(raw, &req) + if err != nil { + app.Fatalf("failed to unmarshal request: %v, %s", err, raw) + return nil + } + return &req +} + func logFinalState(store *manager.DiffFuzzerStore) { log.Logf(0, "status at the end:\n%s", store.PlainTextDump()) @@ -98,8 +113,8 @@ func logFinalState(store *manager.DiffFuzzerStore) { var errSkipFuzzing = errors.New("skip") -func run(baseCtx context.Context, client *api.Client, timeout time.Duration, - store *manager.DiffFuzzerStore) error { +func run(baseCtx context.Context, config *api.FuzzConfig, client *api.Client, + timeout time.Duration, store *manager.DiffFuzzerStore) error { series, err := client.GetSessionSeries(baseCtx, *flagSession) if err != nil { return fmt.Errorf("failed to query the series info: %w", err) @@ -110,7 +125,7 @@ func run(baseCtx context.Context, client *api.Client, timeout time.Duration, const MB = 1000000 log.EnableLogCaching(100000, 10*MB) - base, patched, err := loadConfigs("/configs", *flagConfig, true) + base, patched, err := loadConfigs("/configs", config.Config, true) if err != nil { return fmt.Errorf("failed to load configs: %w", err) } @@ -125,12 +140,12 @@ func run(baseCtx context.Context, client *api.Client, timeout time.Duration, } manager.PatchFocusAreas(patched, series.PatchBodies(), baseSymbols.Text, patchedSymbols.Text) - if *flagCorpusURL != "" { - err := downloadCorpus(baseCtx, patched.Workdir, *flagCorpusURL) + if config.CorpusURL != "" { + err := downloadCorpus(baseCtx, patched.Workdir, config.CorpusURL) if err != nil { return fmt.Errorf("failed to download the corpus: %w", err) } else { - log.Logf(0, "downloaded the corpus from %s", *flagCorpusURL) + log.Logf(0, "downloaded the corpus from %s", config.CorpusURL) } } @@ -167,7 +182,7 @@ func run(baseCtx context.Context, client *api.Client, timeout time.Duration, BaseCrashes: baseCrashes, Store: store, MaxTriageTime: timeout / 2, - FuzzToReachPatched: fuzzToReachPatched(), + FuzzToReachPatched: fuzzToReachPatched(config), BaseCrashKnown: func(ctx context.Context, title string) (bool, error) { ret, err := client.BaseFindingStatus(ctx, &api.BaseFindingInfo{ BuildID: *flagBaseBuild, @@ -396,8 +411,8 @@ func readSectionHashes(file string) (build.SectionHashes, error) { return data, nil } -func fuzzToReachPatched() time.Duration { - if *flagSkipCoverCheck { +func fuzzToReachPatched(config *api.FuzzConfig) time.Duration { + if config.SkipCoverCheck { return 0 } // Allow up to 30 minutes after the corpus triage to reach the patched code. diff --git a/syz-cluster/workflow/fuzz-step/workflow-template.yaml b/syz-cluster/workflow/fuzz-step/workflow-template.yaml index 460659a61..5cf77e6b4 100644 --- a/syz-cluster/workflow/fuzz-step/workflow-template.yaml +++ b/syz-cluster/workflow/fuzz-step/workflow-template.yaml @@ -10,33 +10,27 @@ spec: - name: fuzz-step inputs: parameters: - - name: config - value: "" - name: base-build-id value: "" - name: patched-build-id value: "" - - name: corpus-url - value: "" - - name: skip-cover-check - value: "false" artifacts: - name: base-kernel path: /base - name: patched-kernel path: /patched + - name: config + path: /tmp/config.json timeout: 4h container: image: ${IMAGE_PREFIX}fuzz-step:${IMAGE_TAG} imagePullPolicy: IfNotPresent command: ["/bin/fuzz-step"] args: [ - "--config", "{{inputs.parameters.config}}", + "--config", "/tmp/config.json", "--session", "{{workflow.parameters.session-id}}", "--base_build", "{{inputs.parameters.base-build-id}}", "--patched_build", "{{inputs.parameters.patched-build-id}}", - "--corpus_url", "{{inputs.parameters.corpus-url}}", - "--skip_cover_check={{inputs.parameters.skip-cover-check}}", "--time", "3h", "--workdir", "/workdir", "--vv", "1" |
