diff options
| -rw-r--r-- | prog/prio.go | 6 | ||||
| -rw-r--r-- | prog/rand.go | 2 | ||||
| -rw-r--r-- | syz-fuzzer/proc.go | 5 | ||||
| -rw-r--r-- | syz-manager/manager.go | 63 | ||||
| -rw-r--r-- | syz-manager/rpc.go | 49 |
5 files changed, 67 insertions, 58 deletions
diff --git a/prog/prio.go b/prog/prio.go index ccdab7bda..3a3f31b63 100644 --- a/prog/prio.go +++ b/prog/prio.go @@ -254,7 +254,7 @@ func (target *Target) BuildChoiceTable(corpus []*Prog, enabled map[*Syscall]bool return &ChoiceTable{target, run, enabledCalls} } -func (ct *ChoiceTable) enabled(call int) bool { +func (ct *ChoiceTable) Enabled(call int) bool { return ct.runs[call] != nil } @@ -262,13 +262,13 @@ func (ct *ChoiceTable) choose(r *rand.Rand, bias int) int { if bias < 0 { bias = ct.calls[r.Intn(len(ct.calls))].ID } - if !ct.enabled(bias) { + if !ct.Enabled(bias) { panic("bias to disabled syscall") } run := ct.runs[bias] x := r.Intn(run[len(run)-1]) + 1 res := sort.SearchInts(run, x) - if !ct.enabled(res) { + if !ct.Enabled(res) { panic("selected disabled syscall") } return res diff --git a/prog/rand.go b/prog/rand.go index 019745161..b3d10cf42 100644 --- a/prog/rand.go +++ b/prog/rand.go @@ -379,7 +379,7 @@ func (r *randGen) createResource(s *state, res *ResourceType, dir Dir) (arg Arg, // TODO: reduce priority of less specialized ctors. var metas []*Syscall for _, meta := range metas0 { - if s.ct.enabled(meta.ID) { + if s.ct.Enabled(meta.ID) { metas = append(metas, meta) } } diff --git a/syz-fuzzer/proc.go b/syz-fuzzer/proc.go index d815a58b9..3c39879cc 100644 --- a/syz-fuzzer/proc.go +++ b/syz-fuzzer/proc.go @@ -277,6 +277,11 @@ func (proc *Proc) executeRaw(opts *ipc.ExecOpts, p *prog.Prog, stat Stat) *ipc.P if opts.Flags&ipc.FlagDedupCover == 0 { log.Fatalf("dedup cover is not enabled") } + for _, call := range p.Calls { + if !proc.fuzzer.choiceTable.Enabled(call.Meta.ID) { + panic(fmt.Sprintf("executing disabled syscall %v", call.Meta.Name)) + } + } // Limit concurrency window and do leak checking once in a while. ticket := proc.fuzzer.gate.Enter() diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 2a0b7dd48..f8e97f1ea 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -65,9 +65,10 @@ type Manager struct { dash *dashapi.Dashboard - mu sync.Mutex - phase int - enabledSyscalls []int + mu sync.Mutex + phase int + configEnabledSyscalls []int + targetEnabledSyscalls map[*prog.Syscall]bool candidates []rpctype.RPCCandidate // untriaged inputs from corpus and hub disabledHashes map[string]struct{} @@ -157,27 +158,27 @@ func RunManager(cfg *mgrconfig.Config, target *prog.Target, sysTarget *targets.T } mgr := &Manager{ - cfg: cfg, - vmPool: vmPool, - target: target, - sysTarget: sysTarget, - reporter: reporter, - crashdir: crashdir, - startTime: time.Now(), - stats: &Stats{haveHub: cfg.HubClient != ""}, - crashTypes: make(map[string]bool), - enabledSyscalls: syscalls, - corpus: make(map[string]rpctype.RPCInput), - disabledHashes: make(map[string]struct{}), - memoryLeakFrames: make(map[string]bool), - dataRaceFrames: make(map[string]bool), - fresh: true, - vmStop: make(chan bool), - hubReproQueue: make(chan *Crash, 10), - needMoreRepros: make(chan chan bool), - reproRequest: make(chan chan map[string]bool), - usedFiles: make(map[string]time.Time), - saturatedCalls: make(map[string]bool), + cfg: cfg, + vmPool: vmPool, + target: target, + sysTarget: sysTarget, + reporter: reporter, + crashdir: crashdir, + startTime: time.Now(), + stats: &Stats{haveHub: cfg.HubClient != ""}, + crashTypes: make(map[string]bool), + configEnabledSyscalls: syscalls, + corpus: make(map[string]rpctype.RPCInput), + disabledHashes: make(map[string]struct{}), + memoryLeakFrames: make(map[string]bool), + dataRaceFrames: make(map[string]bool), + fresh: true, + vmStop: make(chan bool), + hubReproQueue: make(chan *Crash, 10), + needMoreRepros: make(chan chan bool), + reproRequest: make(chan chan map[string]bool), + usedFiles: make(map[string]time.Time), + saturatedCalls: make(map[string]bool), } log.Logf(0, "loading corpus...") @@ -469,10 +470,6 @@ func (mgr *Manager) loadCorpus() { fallthrough case currentDBVersion: } - syscalls := make(map[int]bool) - for _, id := range mgr.checkResult.EnabledCalls[mgr.cfg.Sandbox] { - syscalls[id] = true - } broken, tooLong := 0, 0 for key, rec := range mgr.corpusDB.Records { p, err := mgr.target.Deserialize(rec.Val, prog.NonStrict) @@ -489,7 +486,7 @@ func (mgr *Manager) loadCorpus() { disabled := false for _, c := range p.Calls { - if !syscalls[c.Meta.ID] { + if !mgr.targetEnabledSyscalls[c.Meta] { disabled = true break } @@ -1008,7 +1005,7 @@ func (mgr *Manager) fuzzerConnect() ([]rpctype.RPCInput, BugFrames) { return corpus, BugFrames{memoryLeaks: memoryLeakFrames, dataRaces: dataRaceFrames} } -func (mgr *Manager) machineChecked(a *rpctype.CheckArgs) { +func (mgr *Manager) machineChecked(a *rpctype.CheckArgs, enabledSyscalls map[*prog.Syscall]bool) { mgr.mu.Lock() defer mgr.mu.Unlock() if len(mgr.cfg.EnabledSyscalls) != 0 && len(a.DisabledCalls[mgr.cfg.Sandbox]) != 0 { @@ -1016,7 +1013,7 @@ func (mgr *Manager) machineChecked(a *rpctype.CheckArgs) { for _, dc := range a.DisabledCalls[mgr.cfg.Sandbox] { disabled[mgr.target.Syscalls[dc.ID].Name] = dc.Reason } - for _, id := range mgr.enabledSyscalls { + for _, id := range mgr.configEnabledSyscalls { name := mgr.target.Syscalls[id].Name if reason := disabled[name]; reason != "" { log.Logf(0, "disabling %v: %v", name, reason) @@ -1027,12 +1024,12 @@ func (mgr *Manager) machineChecked(a *rpctype.CheckArgs) { log.Fatalf("machine check: %v", a.Error) } log.Logf(0, "machine check:") - log.Logf(0, "%-24v: %v/%v", "syscalls", - len(a.EnabledCalls[mgr.cfg.Sandbox]), len(mgr.target.Syscalls)) + log.Logf(0, "%-24v: %v/%v", "syscalls", len(enabledSyscalls), len(mgr.target.Syscalls)) for _, feat := range a.Features.Supported() { log.Logf(0, "%-24v: %v", feat.Name, feat.Reason) } mgr.checkResult = a + mgr.targetEnabledSyscalls = enabledSyscalls mgr.loadCorpus() mgr.firstConnect = time.Now() } diff --git a/syz-manager/rpc.go b/syz-manager/rpc.go index 91e31dbd9..d734b8da9 100644 --- a/syz-manager/rpc.go +++ b/syz-manager/rpc.go @@ -18,12 +18,13 @@ import ( ) type RPCServer struct { - mgr RPCManagerView - target *prog.Target - enabledSyscalls []int - stats *Stats - sandbox string - batchSize int + mgr RPCManagerView + target *prog.Target + configEnabledSyscalls []int + targetEnabledSyscalls map[*prog.Syscall]bool + stats *Stats + sandbox string + batchSize int mu sync.Mutex fuzzers map[string]*Fuzzer @@ -50,7 +51,7 @@ type BugFrames struct { // RPCManagerView restricts interface between RPCServer and Manager. type RPCManagerView interface { fuzzerConnect() ([]rpctype.RPCInput, BugFrames) - machineChecked(result *rpctype.CheckArgs) + machineChecked(result *rpctype.CheckArgs, enabledSyscalls map[*prog.Syscall]bool) newInput(inp rpctype.RPCInput, sign signal.Signal) bool candidateBatch(size int) []rpctype.RPCCandidate rotateCorpus() bool @@ -58,13 +59,13 @@ type RPCManagerView interface { func startRPCServer(mgr *Manager) (int, error) { serv := &RPCServer{ - mgr: mgr, - target: mgr.target, - enabledSyscalls: mgr.enabledSyscalls, - stats: mgr.stats, - sandbox: mgr.cfg.Sandbox, - fuzzers: make(map[string]*Fuzzer), - rnd: rand.New(rand.NewSource(time.Now().UnixNano())), + mgr: mgr, + target: mgr.target, + configEnabledSyscalls: mgr.configEnabledSyscalls, + stats: mgr.stats, + sandbox: mgr.cfg.Sandbox, + fuzzers: make(map[string]*Fuzzer), + rnd: rand.New(rand.NewSource(time.Now().UnixNano())), } serv.batchSize = 5 if serv.batchSize < mgr.cfg.Procs { @@ -95,7 +96,7 @@ func (serv *RPCServer) Connect(a *rpctype.ConnectArgs, r *rpctype.ConnectRes) er serv.fuzzers[a.Name] = f r.MemoryLeakFrames = bugFrames.memoryLeaks r.DataRaceFrames = bugFrames.dataRaces - r.EnabledCalls = serv.enabledSyscalls + r.EnabledCalls = serv.configEnabledSyscalls r.GitRevision = prog.GitRevision r.TargetRevision = serv.target.Revision // TODO: temporary disabled b/c we suspect this negatively affects fuzzing. @@ -195,14 +196,14 @@ func (serv *RPCServer) Check(a *rpctype.CheckArgs, r *int) error { if serv.checkResult != nil { return nil } - serv.mgr.machineChecked(a) - a.DisabledCalls = nil - serv.checkResult = a - calls := make(map[*prog.Syscall]bool) + serv.targetEnabledSyscalls = make(map[*prog.Syscall]bool) for _, call := range a.EnabledCalls[serv.sandbox] { - calls[serv.target.Syscalls[call]] = true + serv.targetEnabledSyscalls[serv.target.Syscalls[call]] = true } - serv.rotator = prog.MakeRotator(serv.target, calls, serv.rnd) + serv.mgr.machineChecked(a, serv.targetEnabledSyscalls) + a.DisabledCalls = nil + serv.checkResult = a + serv.rotator = prog.MakeRotator(serv.target, serv.targetEnabledSyscalls, serv.rnd) return nil } @@ -220,6 +221,12 @@ func (serv *RPCServer) NewInput(a *rpctype.NewInputArgs, r *int) error { log.Logf(0, "rejecting too long program from fuzzer: %v calls\n%s", len(p.Calls), a.RPCInput.Prog) return nil } + for _, call := range p.Calls { + if !serv.targetEnabledSyscalls[call.Meta] { + log.Logf(0, "rejecting program with disabled call %v:\n%s", call.Meta.Name, a.RPCInput.Prog) + return nil + } + } serv.mu.Lock() defer serv.mu.Unlock() |
