From 9d2ab5dfe7727dfea4b9b279f4edf731acb386ef Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Fri, 25 Jun 2021 17:57:13 +0200 Subject: [PATCH] syz-manager, syz-fuzzer: filter stale glob values in the corpus Corpus may accumulate glob values that are already filtered out by descriptions (e.g. some harmful files), for an example see: https://groups.google.com/g/syzkaller-bugs/c/W_R0O4XWpfY/m/sdwwg2_hAwAJ Pass glob files to the manager and filter out values that are not present in the glob already. Also use the same caching scheme we use for features and enabled syscalls so that fuzzers don't need to scan globs every time. --- pkg/rpctype/rpctype.go | 1 + prog/encoding.go | 3 ++- prog/types.go | 2 +- syz-fuzzer/fuzzer.go | 8 +------- syz-fuzzer/testing.go | 29 +++++++++++++++++++++-------- syz-manager/manager.go | 1 + 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/pkg/rpctype/rpctype.go b/pkg/rpctype/rpctype.go index 94c62c2b3402..07a2e5a6441b 100644 --- a/pkg/rpctype/rpctype.go +++ b/pkg/rpctype/rpctype.go @@ -47,6 +47,7 @@ type CheckArgs struct { EnabledCalls map[string][]int DisabledCalls map[string][]SyscallReason Features *host.Features + GlobFiles map[string][]string } type SyscallReason struct { diff --git a/prog/encoding.go b/prog/encoding.go index e66535e2a025..b389fc10d895 100644 --- a/prog/encoding.go +++ b/prog/encoding.go @@ -549,7 +549,8 @@ func (p *parser) parseArgString(t Type, dir Dir) (Arg, error) { data = append(data, make([]byte, diff)...) } data = data[:size] - if typ.Kind == BufferString && len(typ.Values) != 0 && + if (typ.Kind == BufferString || typ.Kind == BufferGlob) && + len(typ.Values) != 0 && // AUTOGENERATED will be padded by 0's. !strings.HasPrefix(typ.Values[0], "AUTOGENERATED") { matched := false diff --git a/prog/types.go b/prog/types.go index 66ce3ced0d34..86346c50f1ae 100644 --- a/prog/types.go +++ b/prog/types.go @@ -503,7 +503,7 @@ type BufferType struct { RangeEnd uint64 // for BufferBlobRange kind Text TextKind // for BufferText SubKind string - Values []string // possible values for BufferString kind + Values []string // possible values for BufferString and BufferGlob kind NoZ bool // non-zero terminated BufferString/BufferFilename } diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go index da1755c0bb08..0eb4791d3e36 100644 --- a/syz-fuzzer/fuzzer.go +++ b/syz-fuzzer/fuzzer.go @@ -227,6 +227,7 @@ func main() { log.Fatalf("%v", r.CheckResult.Error) } } else { + target.UpdateGlobs(r.CheckResult.GlobFiles) if err = host.Setup(target, r.CheckResult.Features, featureFlags, config.Executor); err != nil { log.Fatal(err) } @@ -300,13 +301,6 @@ func collectMachineInfos(target *prog.Target) ([]byte, []host.KernelModule) { if err != nil { log.Fatalf("failed to collect modules info: %v", err) } - - globFiles, err := host.CollectGlobsInfo(target.GetGlobs()) - if err != nil { - log.Fatalf("faield to collect glob info: %v", err) - } - target.UpdateGlobs(globFiles) - return machineInfo, modules } diff --git a/syz-fuzzer/testing.go b/syz-fuzzer/testing.go index 3e576b034baa..6274c3174cd2 100644 --- a/syz-fuzzer/testing.go +++ b/syz-fuzzer/testing.go @@ -124,6 +124,15 @@ func checkMachine(args *checkArgs) (*rpctype.CheckArgs, error) { if err := checkRevisions(args); err != nil { return nil, err } + globFiles, err := host.CollectGlobsInfo(args.target.GetGlobs()) + if err != nil { + return nil, fmt.Errorf("failed to collect glob info: %v", err) + } + // TODO: make host.DetectSupportedSyscalls below filter out globs with no values. + // Also make prog package more strict with respect to generation/mutation of globs + // with no values (they still can appear in tests and tools). We probably should + // generate an empty string for these and never mutate. + args.target.UpdateGlobs(globFiles) features, err := host.Check(args.target) if err != nil { return nil, err @@ -148,24 +157,28 @@ func checkMachine(args *checkArgs) (*rpctype.CheckArgs, error) { if err := checkSimpleProgram(args, features); err != nil { return nil, err } - return checkCalls(args, features) -} - -func checkCalls(args *checkArgs, features *host.Features) (*rpctype.CheckArgs, error) { res := &rpctype.CheckArgs{ Features: features, EnabledCalls: make(map[string][]int), DisabledCalls: make(map[string][]rpctype.SyscallReason), + GlobFiles: globFiles, + } + if err := checkCalls(args, res); err != nil { + return nil, err } + return res, nil +} + +func checkCalls(args *checkArgs, res *rpctype.CheckArgs) error { sandboxes := []string{args.sandbox} if args.allSandboxes { if args.sandbox != "none" { sandboxes = append(sandboxes, "none") } - if args.sandbox != "setuid" && features[host.FeatureSandboxSetuid].Enabled { + if args.sandbox != "setuid" && res.Features[host.FeatureSandboxSetuid].Enabled { sandboxes = append(sandboxes, "setuid") } - if args.sandbox != "namespace" && features[host.FeatureSandboxNamespace].Enabled { + if args.sandbox != "namespace" && res.Features[host.FeatureSandboxNamespace].Enabled { sandboxes = append(sandboxes, "namespace") } // TODO: Add "android" sandbox here when needed. Will require fixing runtests. @@ -175,7 +188,7 @@ func checkCalls(args *checkArgs, features *host.Features) (*rpctype.CheckArgs, e res.EnabledCalls[sandbox] = enabledCalls res.DisabledCalls[sandbox] = disabledCalls if err != nil { - return res, err + return err } } if args.allSandboxes { @@ -190,7 +203,7 @@ func checkCalls(args *checkArgs, features *host.Features) (*rpctype.CheckArgs, e } res.EnabledCalls[""] = enabled } - return res, nil + return nil } func checkRevisions(args *checkArgs) error { diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 20a8af767a83..28d934c344c0 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -1089,6 +1089,7 @@ func (mgr *Manager) machineChecked(a *rpctype.CheckArgs, enabledSyscalls map[*pr defer mgr.mu.Unlock() mgr.checkResult = a mgr.targetEnabledSyscalls = enabledSyscalls + mgr.target.UpdateGlobs(a.GlobFiles) mgr.loadCorpus() mgr.firstConnect = time.Now() }