aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg/manager/diff.go33
-rw-r--r--syz-cluster/pkg/api/api.go2
-rw-r--r--syz-cluster/workflow/fuzz-step/main.go18
-rw-r--r--syz-cluster/workflow/fuzz-step/main_test.go11
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"))
+}