aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2018-02-18 12:09:37 +0100
committerDmitry Vyukov <dvyukov@google.com>2018-02-19 21:48:20 +0100
commit2be2288ee256f3b84a7de15b82894097a08fd939 (patch)
treeca3bb9ac9f9aba7897d71e735f6f4b0e55ad9711
parentb99141b797e3b90e028f2020a5ef1b13fc97e31d (diff)
syz-fuzzer: don't break syscalls during minimization
If the original call was successful, keep it successful during minimization. Successful calls are much more valuable.
-rw-r--r--syz-fuzzer/proc.go25
-rw-r--r--syz-fuzzer/workqueue.go9
2 files changed, 23 insertions, 11 deletions
diff --git a/syz-fuzzer/proc.go b/syz-fuzzer/proc.go
index 9f7eb6973..605febeb8 100644
--- a/syz-fuzzer/proc.go
+++ b/syz-fuzzer/proc.go
@@ -103,7 +103,7 @@ func (proc *Proc) triageInput(item *WorkTriage) {
panic("should not be called when coverage is disabled")
}
- newSignal := proc.fuzzer.corpusSignalDiff(item.signal)
+ newSignal := proc.fuzzer.corpusSignalDiff(item.info.Signal)
if len(newSignal) == 0 {
return
}
@@ -151,6 +151,11 @@ func (proc *Proc) triageInput(item *WorkTriage) {
continue // The call was not executed.
}
inf := info[call1]
+ if item.info.Errno == 0 && inf.Errno != 0 {
+ // Don't minimize calls from successful to unsuccessful.
+ // Successful calls are much more valuable.
+ return false
+ }
signal := cover.Canonicalize(inf.Signal)
if len(cover.Intersection(newSignal, signal)) == len(newSignal) {
return true
@@ -167,11 +172,11 @@ func (proc *Proc) triageInput(item *WorkTriage) {
proc.fuzzer.sendInputToManager(RpcInput{
Call: call.CallName,
Prog: data,
- Signal: []uint32(cover.Canonicalize(item.signal)),
+ Signal: []uint32(cover.Canonicalize(item.info.Signal)),
Cover: []uint32(inputCover),
})
- proc.fuzzer.addInputToCorpus(item.p, item.signal, sig)
+ proc.fuzzer.addInputToCorpus(item.p, item.info.Signal, sig)
if item.flags&ProgSmashed == 0 {
proc.fuzzer.workQueue.enqueue(&WorkSmash{item.p, item.call})
@@ -228,11 +233,17 @@ func (proc *Proc) executeHintSeed(p *prog.Prog, call int) {
func (proc *Proc) execute(execOpts *ipc.ExecOpts, p *prog.Prog, flags ProgTypes, stat Stat) []ipc.CallInfo {
info := proc.executeRaw(execOpts, p, stat)
for _, callIndex := range proc.fuzzer.checkNewSignal(info) {
+ info := info[callIndex]
+ // info.Signal points to the output shmem region, detach it before queueing.
+ info.Signal = append([]uint32{}, info.Signal...)
+ // None of the caller use Cover, so just nil it instead of detaching.
+ // Note: triage input uses executeRaw to get coverage.
+ info.Cover = nil
proc.fuzzer.workQueue.enqueue(&WorkTriage{
- p: p.Clone(),
- call: callIndex,
- signal: append([]uint32{}, info[callIndex].Signal...),
- flags: flags,
+ p: p.Clone(),
+ call: callIndex,
+ info: info,
+ flags: flags,
})
}
return info
diff --git a/syz-fuzzer/workqueue.go b/syz-fuzzer/workqueue.go
index 80905af26..62648336c 100644
--- a/syz-fuzzer/workqueue.go
+++ b/syz-fuzzer/workqueue.go
@@ -6,6 +6,7 @@ package main
import (
"sync"
+ "github.com/google/syzkaller/pkg/ipc"
"github.com/google/syzkaller/prog"
)
@@ -38,10 +39,10 @@ const (
// During triage we understand if these programs in fact give new coverage,
// and if yes, minimize them and add to corpus.
type WorkTriage struct {
- p *prog.Prog
- call int
- signal []uint32
- flags ProgTypes
+ p *prog.Prog
+ call int
+ info ipc.CallInfo
+ flags ProgTypes
}
// WorkCandidate are programs from hub.