mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-26 21:00:30 +00:00
syz-manager: more consistently check disabled syscalls
We have program "validity" check duplicated 4 times (initially it was just "does it deserialize?"). Then we added program length and disabled syscall. But some of the sites have only a subset of checks. Factor out program checking procedure into a separate function and use it at all sites.
This commit is contained in:
parent
9cea41ad33
commit
a44eb8f7ea
@ -21,7 +21,7 @@ func (mgr *Manager) hubSyncLoop() {
|
||||
cfg: mgr.cfg,
|
||||
target: mgr.target,
|
||||
stats: mgr.stats,
|
||||
enabledCalls: mgr.checkResult.EnabledCalls[mgr.cfg.Sandbox],
|
||||
enabledCalls: mgr.targetEnabledSyscalls,
|
||||
leak: mgr.checkResult.Features[host.FeatureLeak].Enabled,
|
||||
fresh: mgr.fresh,
|
||||
hubReproQueue: mgr.hubReproQueue,
|
||||
@ -37,7 +37,7 @@ type HubConnector struct {
|
||||
cfg *mgrconfig.Config
|
||||
target *prog.Target
|
||||
stats *Stats
|
||||
enabledCalls []int
|
||||
enabledCalls map[*prog.Syscall]bool
|
||||
leak bool
|
||||
fresh bool
|
||||
hubCorpus map[hash.Sig]bool
|
||||
@ -80,8 +80,8 @@ func (hc *HubConnector) connect(corpus [][]byte) (*rpctype.RPCClient, error) {
|
||||
Manager: hc.cfg.Name,
|
||||
Fresh: hc.fresh,
|
||||
}
|
||||
for _, id := range hc.enabledCalls {
|
||||
a.Calls = append(a.Calls, hc.target.Syscalls[id].Name)
|
||||
for call := range hc.enabledCalls {
|
||||
a.Calls = append(a.Calls, call.Name)
|
||||
}
|
||||
hubCorpus := make(map[hash.Sig]bool)
|
||||
for _, inp := range corpus {
|
||||
@ -171,8 +171,10 @@ func (hc *HubConnector) processProgs(progs [][]byte) int {
|
||||
dropped := 0
|
||||
candidates := make([][]byte, 0, len(progs))
|
||||
for _, inp := range progs {
|
||||
p, err := hc.target.Deserialize(inp, prog.NonStrict)
|
||||
if err != nil || len(p.Calls) > prog.MaxCalls {
|
||||
bad, disabled := checkProgram(hc.target, hc.enabledCalls, inp)
|
||||
if bad || disabled {
|
||||
log.Logf(0, "rejecting program from hub (bad=%v, disabled=%v):\n%s",
|
||||
bad, disabled, inp)
|
||||
dropped++
|
||||
continue
|
||||
}
|
||||
@ -185,7 +187,10 @@ func (hc *HubConnector) processProgs(progs [][]byte) int {
|
||||
func (hc *HubConnector) processRepros(repros [][]byte) int {
|
||||
dropped := 0
|
||||
for _, repro := range repros {
|
||||
if _, err := hc.target.Deserialize(repro, prog.NonStrict); err != nil {
|
||||
bad, disabled := checkProgram(hc.target, hc.enabledCalls, repro)
|
||||
if bad || disabled {
|
||||
log.Logf(0, "rejecting repro from hub (bad=%v, disabled=%v):\n%s",
|
||||
bad, disabled, repro)
|
||||
dropped++
|
||||
continue
|
||||
}
|
||||
|
@ -470,27 +470,14 @@ func (mgr *Manager) loadCorpus() {
|
||||
fallthrough
|
||||
case currentDBVersion:
|
||||
}
|
||||
broken, tooLong := 0, 0
|
||||
broken := 0
|
||||
for key, rec := range mgr.corpusDB.Records {
|
||||
p, err := mgr.target.Deserialize(rec.Val, prog.NonStrict)
|
||||
if err != nil {
|
||||
bad, disabled := checkProgram(mgr.target, mgr.targetEnabledSyscalls, rec.Val)
|
||||
if bad {
|
||||
mgr.corpusDB.Delete(key)
|
||||
broken++
|
||||
continue
|
||||
}
|
||||
if len(p.Calls) > prog.MaxCalls {
|
||||
mgr.corpusDB.Delete(key)
|
||||
tooLong++
|
||||
continue
|
||||
}
|
||||
|
||||
disabled := false
|
||||
for _, c := range p.Calls {
|
||||
if !mgr.targetEnabledSyscalls[c.Meta] {
|
||||
disabled = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if disabled {
|
||||
// This program contains a disabled syscall.
|
||||
// We won't execute it, but remember its hash so
|
||||
@ -505,8 +492,8 @@ func (mgr *Manager) loadCorpus() {
|
||||
})
|
||||
}
|
||||
mgr.fresh = len(mgr.corpusDB.Records) == 0
|
||||
log.Logf(0, "%-24v: %v (deleted %v broken, %v too long)",
|
||||
"corpus", len(mgr.candidates), broken, tooLong)
|
||||
log.Logf(0, "%-24v: %v (deleted %v broken)",
|
||||
"corpus", len(mgr.candidates), broken)
|
||||
|
||||
// Now this is ugly.
|
||||
// We duplicate all inputs in the corpus and shuffle the second part.
|
||||
@ -525,6 +512,22 @@ func (mgr *Manager) loadCorpus() {
|
||||
mgr.phase = phaseLoadedCorpus
|
||||
}
|
||||
|
||||
func checkProgram(target *prog.Target, enabled map[*prog.Syscall]bool, data []byte) (bad, disabled bool) {
|
||||
p, err := target.Deserialize(data, prog.NonStrict)
|
||||
if err != nil {
|
||||
return true, true
|
||||
}
|
||||
if len(p.Calls) > prog.MaxCalls {
|
||||
return true, true
|
||||
}
|
||||
for _, c := range p.Calls {
|
||||
if !enabled[c.Meta] {
|
||||
return false, true
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (mgr *Manager) runInstance(index int) (*Crash, error) {
|
||||
mgr.checkUsedFiles()
|
||||
inst, err := mgr.vmPool.Create(index)
|
||||
|
@ -211,22 +211,11 @@ func (serv *RPCServer) NewInput(a *rpctype.NewInputArgs, r *int) error {
|
||||
inputSignal := a.Signal.Deserialize()
|
||||
log.Logf(4, "new input from %v for syscall %v (signal=%v, cover=%v)",
|
||||
a.Name, a.Call, inputSignal.Len(), len(a.Cover))
|
||||
p, err := serv.target.Deserialize(a.RPCInput.Prog, prog.NonStrict)
|
||||
if err != nil {
|
||||
// This should not happen, but we see such cases episodically (probably corrupted VM memory).
|
||||
log.Logf(0, "failed to deserialize program from fuzzer: %v\n%s", err, a.RPCInput.Prog)
|
||||
bad, disabled := checkProgram(serv.target, serv.targetEnabledSyscalls, a.RPCInput.Prog)
|
||||
if bad || disabled {
|
||||
log.Logf(0, "rejecting program from fuzzer (bad=%v, disabled=%v):\n%s", bad, disabled, a.RPCInput.Prog)
|
||||
return nil
|
||||
}
|
||||
if len(p.Calls) > prog.MaxCalls {
|
||||
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()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user