diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-01-18 16:10:34 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-01-18 19:58:12 +0100 |
| commit | ffe327412b008a8673e41cd6cbf08f3e98a14af9 (patch) | |
| tree | 17c752e181bb50376a939bb3ea6f867acbe5a85f | |
| parent | f03e9df1b620f6ca029ed9cac7b3192d9d09268a (diff) | |
syz-fuzzer: don't reminimize all programs from corpus on start
Minimization takes considerable time on start, but the programs were already minimized.
There are some chances that we could minimize it better this time,
but still it does not worth very slow start (which is especially painful for development).
| -rw-r--r-- | rpctype/rpctype.go | 7 | ||||
| -rw-r--r-- | syz-fuzzer/fuzzer.go | 70 | ||||
| -rw-r--r-- | syz-manager/manager.go | 12 |
3 files changed, 57 insertions, 32 deletions
diff --git a/rpctype/rpctype.go b/rpctype/rpctype.go index 31e36fbfb..f64e90f4f 100644 --- a/rpctype/rpctype.go +++ b/rpctype/rpctype.go @@ -12,6 +12,11 @@ type RpcInput struct { Cover []uint32 } +type RpcCandidate struct { + Prog []byte + Minimized bool +} + type ConnectArgs struct { Name string } @@ -39,7 +44,7 @@ type PollArgs struct { } type PollRes struct { - Candidates [][]byte + Candidates []RpcCandidate NewInputs []RpcInput } diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go index ae9b05c12..814986316 100644 --- a/syz-fuzzer/fuzzer.go +++ b/syz-fuzzer/fuzzer.go @@ -54,9 +54,15 @@ func hash(data []byte) Sig { } type Input struct { - p *prog.Prog - call int - cover cover.Cover + p *prog.Prog + call int + cover cover.Cover + minimized bool +} + +type Candidate struct { + p *prog.Prog + minimized bool } var ( @@ -73,7 +79,7 @@ var ( triageMu sync.RWMutex triage []Input - candidates []*prog.Prog + candidates []Candidate gate *ipc.Gate @@ -197,10 +203,10 @@ func main() { continue } else if len(candidates) != 0 { last := len(candidates) - 1 - p := candidates[last] + candidate := candidates[last] candidates = candidates[:last] triageMu.Unlock() - execute(pid, env, p, &statExecCandidate) + execute(pid, env, candidate.p, candidate.minimized, &statExecCandidate) continue } else { triageMu.Unlock() @@ -215,10 +221,10 @@ func main() { corpusMu.RUnlock() p := prog.Generate(rnd, programLength, ct) Logf(1, "#%v: generated: %s", i, p) - execute(pid, env, p, &statExecGen) + execute(pid, env, p, false, &statExecGen) p.Mutate(rnd, programLength, ct, nil) Logf(1, "#%v: mutated: %s", i, p) - execute(pid, env, p, &statExecFuzz) + execute(pid, env, p, false, &statExecFuzz) } else { // Mutate an existing prog. p0 := corpus[rnd.Intn(len(corpus))] @@ -226,7 +232,7 @@ func main() { p.Mutate(rs, programLength, ct, corpus) corpusMu.RUnlock() Logf(1, "#%v: mutated: %s <- %s", i, p, p0) - execute(pid, env, p, &statExecFuzz) + execute(pid, env, p, false, &statExecFuzz) } } }() @@ -276,8 +282,8 @@ func main() { for _, inp := range r.NewInputs { addInput(inp) } - for _, data := range r.Candidates { - p, err := prog.Deserialize(data) + for _, candidate := range r.Candidates { + p, err := prog.Deserialize(candidate.Prog) if err != nil { panic(err) } @@ -287,7 +293,7 @@ func main() { corpusMu.Unlock() } else { triageMu.Lock() - candidates = append(candidates, p) + candidates = append(candidates, Candidate{p, candidate.Minimized}) triageMu.Unlock() } } @@ -427,21 +433,24 @@ func triageInput(pid int, env *ipc.Env, inp Input) { if len(newCover) == 0 { return } - inp.p, inp.call = prog.Minimize(inp.p, inp.call, func(p1 *prog.Prog, call1 int) bool { - allCover := execute1(pid, env, p1, &statExecMinimize) - coverMu.RLock() - defer coverMu.RUnlock() - if len(allCover[call1]) == 0 { - return false // The call was not executed. - } - cov := allCover[call1] - if len(cover.Intersection(newCover, cov)) != len(newCover) { - return false - } - minCover = cover.Intersection(minCover, cov) - return true - }, false) + if !inp.minimized { + inp.p, inp.call = prog.Minimize(inp.p, inp.call, func(p1 *prog.Prog, call1 int) bool { + allCover := execute1(pid, env, p1, &statExecMinimize) + coverMu.RLock() + defer coverMu.RUnlock() + + if len(allCover[call1]) == 0 { + return false // The call was not executed. + } + cov := allCover[call1] + if len(cover.Intersection(newCover, cov)) != len(newCover) { + return false + } + minCover = cover.Intersection(minCover, cov) + return true + }, false) + } inp.cover = minCover atomic.AddUint64(&statNewInput, 1) @@ -462,7 +471,7 @@ func triageInput(pid int, env *ipc.Env, inp Input) { corpusHashes[hash(data)] = struct{}{} } -func execute(pid int, env *ipc.Env, p *prog.Prog, stat *uint64) { +func execute(pid int, env *ipc.Env, p *prog.Prog, minimized bool, stat *uint64) { allCover := execute1(pid, env, p, stat) coverMu.RLock() defer coverMu.RUnlock() @@ -480,7 +489,12 @@ func execute(pid int, env *ipc.Env, p *prog.Prog, stat *uint64) { coverMu.Unlock() coverMu.RLock() - inp := Input{p.Clone(), i, cover.Copy(cov)} + inp := Input{ + p: p.Clone(), + call: i, + cover: cover.Copy(cov), + minimized: minimized, + } triageMu.Lock() triage = append(triage, inp) triageMu.Unlock() diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 9a4d4af8d..93f0e87d0 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -58,7 +58,7 @@ type Manager struct { enabledSyscalls string enabledCalls []string // as determined by fuzzer - candidates [][]byte // untriaged inputs + candidates []RpcCandidate // untriaged inputs disabledHashes []string corpus []RpcInput corpusCover []cover.Cover @@ -158,7 +158,10 @@ func RunManager(cfg *config.Config, syscalls map[int]bool) { mgr.disabledHashes = append(mgr.disabledHashes, sig.String()) continue } - mgr.candidates = append(mgr.candidates, rec.Val) + mgr.candidates = append(mgr.candidates, RpcCandidate{ + Prog: rec.Val, + Minimized: true, // don't reminimize programs from corpus, it takes lots of time on start + }) } mgr.fresh = len(mgr.corpusDB.Records) == 0 Logf(0, "loaded %v programs (%v total)", len(mgr.candidates), len(mgr.corpusDB.Records)) @@ -743,7 +746,10 @@ func (mgr *Manager) hubSync() { dropped++ continue } - mgr.candidates = append(mgr.candidates, inp) + mgr.candidates = append(mgr.candidates, RpcCandidate{ + Prog: inp, + Minimized: false, // don't trust programs from hub + }) } mgr.stats["hub add"] += uint64(len(a.Add)) mgr.stats["hub del"] += uint64(len(a.Del)) |
