diff options
| -rw-r--r-- | pkg/manager/diff.go | 33 | ||||
| -rw-r--r-- | syz-cluster/pkg/api/api.go | 2 | ||||
| -rw-r--r-- | syz-cluster/workflow/fuzz-step/main.go | 18 | ||||
| -rw-r--r-- | syz-cluster/workflow/fuzz-step/main_test.go | 11 |
4 files changed, 47 insertions, 17 deletions
diff --git a/pkg/manager/diff.go b/pkg/manager/diff.go index 8b57e5807..b6423e4c9 100644 --- a/pkg/manager/diff.go +++ b/pkg/manager/diff.go @@ -52,11 +52,11 @@ type DiffFuzzerConfig struct { // trying to reach the modified code. The time is counted since the moment // 99% of the corpus is triaged. FuzzToReachPatched time.Duration - // The callback may be used to consult external systems on whether the - // base kernel has ever crashed with the given title. - // It may help reduce the false positive rate and prevent unnecessary - // bug reproductions. - BaseCrashKnown func(context.Context, string) (bool, error) + // The callback may be used to consult external systems on whether + // the crash should be ignored. E.g. because it doesn't match the filter or + // the particular base kernel has already been seen to crash with the given title. + // It helps reduce the number of unnecessary reproductions. + IgnoreCrash func(context.Context, string) (bool, error) } func (cfg *DiffFuzzerConfig) TriageDeadline() <-chan time.Time { @@ -198,10 +198,11 @@ loop: // A sanity check: the base kernel might have crashed with the same title // since the moment we have stared the reproduction / running on the repro base. - crashesOnBase := dc.everCrashedBase(ctx, ret.reproReport.Title) - if ret.crashReport == nil && crashesOnBase { + ignored := dc.ignoreCrash(ctx, ret.reproReport.Title) + if ret.crashReport == nil && ignored { // Report it as error so that we could at least find it in the logs. - log.Errorf("repro didn't crash base, but base itself crashed: %s", ret.reproReport.Title) + log.Errorf("resulting crash of an approved repro result is to be ignored: %s", + ret.reproReport.Title) } else if ret.crashReport == nil { dc.store.BaseNotCrashed(ret.reproReport.Title) select { @@ -260,20 +261,20 @@ loop: return g.Wait() } -func (dc *diffContext) everCrashedBase(ctx context.Context, title string) bool { +func (dc *diffContext) ignoreCrash(ctx context.Context, title string) bool { if dc.store.EverCrashedBase(title) { return true } // Let's try to ask the external systems about it as well. - if dc.cfg.BaseCrashKnown != nil { - known, err := dc.cfg.BaseCrashKnown(ctx, title) + if dc.cfg.IgnoreCrash != nil { + ignore, err := dc.cfg.IgnoreCrash(ctx, title) if err != nil { - log.Logf(0, "a call to BaseCrashKnown failed: %v", err) + log.Logf(0, "a call to IgnoreCrash failed: %v", err) } else { - if known { - log.Logf(0, "base crash %q is already known", title) + if ignore { + log.Logf(0, "base crash %q is to be ignored", title) } - return known + return ignore } } return false @@ -382,7 +383,7 @@ func (dc *diffContext) NeedRepro(crash *Crash) bool { ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() - if dc.everCrashedBase(ctx, crash.Title) { + if dc.ignoreCrash(ctx, crash.Title) { return false } if dc.reproAttempts[crash.Title] > maxReproAttempts { diff --git a/syz-cluster/pkg/api/api.go b/syz-cluster/pkg/api/api.go index 49a5a7f45..a634fe344 100644 --- a/syz-cluster/pkg/api/api.go +++ b/syz-cluster/pkg/api/api.go @@ -26,6 +26,8 @@ type FuzzConfig struct { CorpusURL string `json:"corpus_url"` // Don't expect kernel coverage for the patched area. SkipCoverCheck bool `json:"skip_cover_check"` + // Only report the bugs that match the regexp. + BugTitleRe string `json:"bug_title_re"` } // The triage step of the workflow will request these from controller. diff --git a/syz-cluster/workflow/fuzz-step/main.go b/syz-cluster/workflow/fuzz-step/main.go index fa690dc93..72b50c943 100644 --- a/syz-cluster/workflow/fuzz-step/main.go +++ b/syz-cluster/workflow/fuzz-step/main.go @@ -14,6 +14,7 @@ import ( "net/http" "os" "path/filepath" + "regexp" "time" "github.com/google/syzkaller/pkg/build" @@ -183,7 +184,11 @@ func run(baseCtx context.Context, config *api.FuzzConfig, client *api.Client, Store: store, MaxTriageTime: timeout / 2, FuzzToReachPatched: fuzzToReachPatched(config), - BaseCrashKnown: func(ctx context.Context, title string) (bool, error) { + IgnoreCrash: func(ctx context.Context, title string) (bool, error) { + if !titleMatchesFilter(config, title) { + log.Logf(1, "crash %q doesn't match the filter", title) + return true, nil + } ret, err := client.BaseFindingStatus(ctx, &api.BaseFindingInfo{ BuildID: *flagBaseBuild, Title: title, @@ -191,6 +196,9 @@ func run(baseCtx context.Context, config *api.FuzzConfig, client *api.Client, if err != nil { return false, err } + if ret.Observed { + log.Logf(1, "crash %q is already known", title) + } return ret.Observed, nil }, }) @@ -382,6 +390,14 @@ func shouldSkipFuzzing(base, patched build.SectionHashes) bool { return false } +func titleMatchesFilter(config *api.FuzzConfig, title string) bool { + matched, err := regexp.MatchString(config.BugTitleRe, title) + if err != nil { + app.Fatalf("invalid BugTitleRe regexp: %v", err) + } + return matched +} + func readSymbolHashes() (base, patched build.SectionHashes, err error) { // These are saved by the build step. base, err = readSectionHashes("/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 038690bd6..6f305a818 100644 --- a/syz-cluster/workflow/fuzz-step/main_test.go +++ b/syz-cluster/workflow/fuzz-step/main_test.go @@ -12,6 +12,7 @@ import ( "github.com/google/syzkaller/pkg/build" "github.com/google/syzkaller/pkg/osutil" + "github.com/google/syzkaller/syz-cluster/pkg/api" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -117,3 +118,13 @@ func TestShouldSkipFuzzing(t *testing.T) { )) }) } + +func TestBugTitleRe(t *testing.T) { + assert.True(t, titleMatchesFilter(&api.FuzzConfig{}, "any title must match")) + assert.True(t, titleMatchesFilter(&api.FuzzConfig{ + BugTitleRe: `^Prefix:`, + }, "Prefix: must pass")) + assert.False(t, titleMatchesFilter(&api.FuzzConfig{ + BugTitleRe: `^Prefix:`, + }, "Without prefix")) +} |
