Skip to content

Commit

Permalink
syz-fuzzer: don't break syscalls during minimization
Browse files Browse the repository at this point in the history
If the original call was successful, keep it successful during minimization.
Successful calls are much more valuable.
  • Loading branch information
dvyukov committed Feb 19, 2018
1 parent b99141b commit 2be2288
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 11 deletions.
25 changes: 18 additions & 7 deletions syz-fuzzer/proc.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand All @@ -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})
Expand Down Expand Up @@ -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
Expand Down
9 changes: 5 additions & 4 deletions syz-fuzzer/workqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package main
import (
"sync"

"github.com/google/syzkaller/pkg/ipc"
"github.com/google/syzkaller/prog"
)

Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 2be2288

Please sign in to comment.