diff options
35 files changed, 266 insertions, 438 deletions
@@ -156,7 +156,8 @@ manager: descriptions GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-manager github.com/google/syzkaller/syz-manager runtest: descriptions - GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-runtest github.com/google/syzkaller/tools/syz-runtest + # TODO: fold syz-runtest into syz-manager. + # GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-runtest github.com/google/syzkaller/tools/syz-runtest fuzzer: descriptions GOOS=$(TARGETGOOS) GOARCH=$(TARGETGOARCH) $(GO) build $(GOTARGETFLAGS) -o ./bin/$(TARGETOS)_$(TARGETVMARCH)/syz-fuzzer$(EXE) github.com/google/syzkaller/syz-fuzzer @@ -213,10 +214,12 @@ bisect: descriptions GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-bisect github.com/google/syzkaller/tools/syz-bisect verifier: descriptions - GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-verifier github.com/google/syzkaller/syz-verifier + # TODO: switch syz-verifier to use syz-fuzzer. + # GOOS=$(HOSTOS) GOARCH=$(HOSTARCH) $(HOSTGO) build $(GOHOSTFLAGS) -o ./bin/syz-verifier github.com/google/syzkaller/syz-verifier runner: descriptions - GOOS=$(TARGETGOOS) GOARCH=$(TARGETGOARCH) $(GO) build $(GOTARGETFLAGS) -o ./bin/$(TARGETOS)_$(TARGETVMARCH)/syz-runner$(EXE) github.com/google/syzkaller/syz-runner + # TODO: switch syz-verifier to use syz-fuzzer. + # GOOS=$(TARGETGOOS) GOARCH=$(TARGETGOARCH) $(GO) build $(GOTARGETFLAGS) -o ./bin/$(TARGETOS)_$(TARGETVMARCH)/syz-runner$(EXE) github.com/google/syzkaller/syz-runner # `extract` extracts const files from various kernel sources, and may only # re-generate parts of files. diff --git a/pkg/flatrpc/helpers.go b/pkg/flatrpc/helpers.go index 92e583400..843b281d3 100644 --- a/pkg/flatrpc/helpers.go +++ b/pkg/flatrpc/helpers.go @@ -3,6 +3,11 @@ package flatrpc +import ( + "slices" + "syscall" +) + const AllFeatures = ^Feature(0) // Flatbuffers compiler adds T suffix to object API types, which are actual structs representing types. @@ -26,3 +31,40 @@ type CallInfo = CallInfoRawT type Comparison = ComparisonRawT type ProgInfo = ProgInfoRawT type ExecResult = ExecResultRawT + +func (pi *ProgInfo) Clone() *ProgInfo { + if pi == nil { + return nil + } + ret := *pi + ret.Extra = ret.Extra.clone() + ret.Calls = make([]*CallInfo, len(pi.Calls)) + for i, call := range pi.Calls { + ret.Calls[i] = call.clone() + } + return &ret +} + +func (ci *CallInfo) clone() *CallInfo { + if ci == nil { + return nil + } + ret := *ci + ret.Signal = slices.Clone(ret.Signal) + ret.Cover = slices.Clone(ret.Cover) + ret.Comps = slices.Clone(ret.Comps) + return &ret +} + +func EmptyProgInfo(calls int) *ProgInfo { + info := &ProgInfo{} + for i := 0; i < calls; i++ { + info.Calls = append(info.Calls, &CallInfo{ + // Store some unsuccessful errno in the case we won't get any result. + // It also won't have CallExecuted flag, but it's handy to make it + // look failed based on errno as well. + Error: int32(syscall.ENOSYS), + }) + } + return info +} diff --git a/pkg/fuzzer/fuzzer.go b/pkg/fuzzer/fuzzer.go index 92b4c8bf1..f079e1dc7 100644 --- a/pkg/fuzzer/fuzzer.go +++ b/pkg/fuzzer/fuzzer.go @@ -124,12 +124,12 @@ func (fuzzer *Fuzzer) processResult(req *queue.Request, res *queue.Result, flags // If we are already triaging this exact prog, this is flaky coverage. if req.ExecOpts.ExecFlags&flatrpc.ExecFlagCollectSignal > 0 && res.Info != nil && !inTriage { for call, info := range res.Info.Calls { - fuzzer.triageProgCall(req.Prog, &info, call, flags) + fuzzer.triageProgCall(req.Prog, info, call, flags) } - fuzzer.triageProgCall(req.Prog, &res.Info.Extra, -1, flags) + fuzzer.triageProgCall(req.Prog, res.Info.Extra, -1, flags) } if res.Info != nil { - fuzzer.statExecTime.Add(int(res.Info.Elapsed.Milliseconds())) + fuzzer.statExecTime.Add(int(res.Info.Elapsed / 1e6)) } } @@ -148,7 +148,10 @@ type Config struct { NewInputFilter func(call string) bool } -func (fuzzer *Fuzzer) triageProgCall(p *prog.Prog, info *ipc.CallInfo, call int, flags ProgTypes) { +func (fuzzer *Fuzzer) triageProgCall(p *prog.Prog, info *flatrpc.CallInfo, call int, flags ProgTypes) { + if info == nil { + return + } prio := signalPrio(p, info, call) newMaxSignal := fuzzer.Cover.addRawMaxSignal(info.Signal, prio) if newMaxSignal.Empty() { @@ -166,18 +169,18 @@ func (fuzzer *Fuzzer) triageProgCall(p *prog.Prog, info *ipc.CallInfo, call int, fuzzer.startJob(fuzzer.statJobsTriage, &triageJob{ p: p.Clone(), call: call, - info: *info, + info: info, newSignal: newMaxSignal, flags: flags, queue: queue.Append(), }) } -func signalPrio(p *prog.Prog, info *ipc.CallInfo, call int) (prio uint8) { +func signalPrio(p *prog.Prog, info *flatrpc.CallInfo, call int) (prio uint8) { if call == -1 { return 0 } - if info.Errno == 0 { + if info.Error == 0 { prio |= 1 << 1 } if !p.Target.CallContainsAny(p.Calls[call]) { diff --git a/pkg/fuzzer/fuzzer_test.go b/pkg/fuzzer/fuzzer_test.go index cb58a4e10..07e09e25a 100644 --- a/pkg/fuzzer/fuzzer_test.go +++ b/pkg/fuzzer/fuzzer_test.go @@ -186,16 +186,16 @@ var crc32q = crc32.MakeTable(0xD5828281) func emulateExec(req *queue.Request) (*queue.Result, string, error) { serializedLines := bytes.Split(req.Prog.Serialize(), []byte("\n")) - var info ipc.ProgInfo + var info flatrpc.ProgInfo for i, call := range req.Prog.Calls { - cover := uint32(call.Meta.ID*1024) + - crc32.Checksum(serializedLines[i], crc32q)%4 - callInfo := ipc.CallInfo{} + cover := []uint32{uint32(call.Meta.ID*1024) + + crc32.Checksum(serializedLines[i], crc32q)%4} + callInfo := &flatrpc.CallInfo{} if req.ExecOpts.ExecFlags&flatrpc.ExecFlagCollectCover > 0 { - callInfo.Cover = []uint32{cover} + callInfo.Cover = cover } if req.ExecOpts.ExecFlags&flatrpc.ExecFlagCollectSignal > 0 { - callInfo.Signal = []uint32{cover} + callInfo.Signal = cover } info.Calls = append(info.Calls, callInfo) } diff --git a/pkg/fuzzer/job.go b/pkg/fuzzer/job.go index 4e605f1c2..a5a22b2e8 100644 --- a/pkg/fuzzer/job.go +++ b/pkg/fuzzer/job.go @@ -11,7 +11,6 @@ import ( "github.com/google/syzkaller/pkg/cover" "github.com/google/syzkaller/pkg/flatrpc" "github.com/google/syzkaller/pkg/fuzzer/queue" - "github.com/google/syzkaller/pkg/ipc" "github.com/google/syzkaller/pkg/signal" "github.com/google/syzkaller/pkg/stats" "github.com/google/syzkaller/prog" @@ -83,7 +82,7 @@ func candidateRequest(fuzzer *Fuzzer, input Candidate) (*queue.Request, ProgType type triageJob struct { p *prog.Prog call int - info ipc.CallInfo + info *flatrpc.CallInfo newSignal signal.Signal flags ProgTypes fuzzer *Fuzzer @@ -172,7 +171,7 @@ func (job *triageJob) deflake(exec func(*queue.Request, ProgTypes) *queue.Result stop = true return } - if !reexecutionSuccess(result.Info, &job.info, job.call) { + if !reexecutionSuccess(result.Info, job.info, job.call) { // The call was not executed or failed. continue } @@ -213,7 +212,7 @@ func (job *triageJob) minimize(newSignal signal.Signal) (stop bool) { return false } info := result.Info - if !reexecutionSuccess(info, &job.info, call1) { + if !reexecutionSuccess(info, job.info, call1) { // The call was not executed or failed. continue } @@ -227,25 +226,28 @@ func (job *triageJob) minimize(newSignal signal.Signal) (stop bool) { return stop } -func reexecutionSuccess(info *ipc.ProgInfo, oldInfo *ipc.CallInfo, call int) bool { +func reexecutionSuccess(info *flatrpc.ProgInfo, oldInfo *flatrpc.CallInfo, call int) bool { if info == nil || len(info.Calls) == 0 { return false } if call != -1 { // Don't minimize calls from successful to unsuccessful. // Successful calls are much more valuable. - if oldInfo.Errno == 0 && info.Calls[call].Errno != 0 { + if oldInfo.Error == 0 && info.Calls[call].Error != 0 { return false } return len(info.Calls[call].Signal) != 0 } - return len(info.Extra.Signal) != 0 + return info.Extra != nil && len(info.Extra.Signal) != 0 } -func getSignalAndCover(p *prog.Prog, info *ipc.ProgInfo, call int) (signal.Signal, []uint32) { - inf := &info.Extra +func getSignalAndCover(p *prog.Prog, info *flatrpc.ProgInfo, call int) (signal.Signal, []uint32) { + inf := info.Extra if call != -1 { - inf = &info.Calls[call] + inf = info.Calls[call] + } + if inf == nil { + return nil, nil } return signal.FromRaw(inf.Signal, signalPrio(p, inf, call)), inf.Cover } @@ -332,7 +334,7 @@ func (job *smashJob) faultInjection(fuzzer *Fuzzer) { } info := result.Info if info != nil && len(info.Calls) > job.call && - info.Calls[job.call].Flags&ipc.CallFaultInjected == 0 { + info.Calls[job.call].Flags&flatrpc.CallFlagFaultInjected == 0 { break } } @@ -358,13 +360,17 @@ func (job *hintsJob) run(fuzzer *Fuzzer) { if result.Stop() || result.Info == nil { return } + got := make(prog.CompMap) + for _, cmp := range result.Info.Calls[job.call].Comps { + got.AddComp(cmp.Op1, cmp.Op2) + } + if len(got) == 0 { + return + } if i == 0 { - comps = result.Info.Calls[job.call].Comps - if len(comps) == 0 { - return - } + comps = got } else { - comps.InplaceIntersect(result.Info.Calls[job.call].Comps) + comps.InplaceIntersect(got) } } diff --git a/pkg/fuzzer/job_test.go b/pkg/fuzzer/job_test.go index b7718134b..70d083be5 100644 --- a/pkg/fuzzer/job_test.go +++ b/pkg/fuzzer/job_test.go @@ -6,8 +6,8 @@ package fuzzer import ( "testing" + "github.com/google/syzkaller/pkg/flatrpc" "github.com/google/syzkaller/pkg/fuzzer/queue" - "github.com/google/syzkaller/pkg/ipc" "github.com/google/syzkaller/pkg/signal" "github.com/google/syzkaller/prog" "github.com/google/syzkaller/sys/targets" @@ -24,7 +24,7 @@ func TestDeflakeFail(t *testing.T) { testJob := &triageJob{ p: prog, - info: ipc.CallInfo{}, + info: &flatrpc.CallInfo{}, newSignal: signal.FromRaw([]uint32{0, 1, 2, 3, 4}, 0), } @@ -50,7 +50,7 @@ func TestDeflakeSuccess(t *testing.T) { testJob := &triageJob{ p: prog, - info: ipc.CallInfo{}, + info: &flatrpc.CallInfo{}, newSignal: signal.FromRaw([]uint32{0, 1, 2}, 0), } run := 0 @@ -80,12 +80,12 @@ func TestDeflakeSuccess(t *testing.T) { assert.ElementsMatch(t, []uint32{0, 2}, ret.newStableSignal.ToRaw()) } -func fakeResult(errno int, signal, cover []uint32) *queue.Result { +func fakeResult(errno int32, signal, cover []uint32) *queue.Result { return &queue.Result{ - Info: &ipc.ProgInfo{ - Calls: []ipc.CallInfo{ + Info: &flatrpc.ProgInfo{ + Calls: []*flatrpc.CallInfo{ { - Errno: errno, + Error: errno, Signal: signal, Cover: cover, }, diff --git a/pkg/fuzzer/queue/queue.go b/pkg/fuzzer/queue/queue.go index 36226299a..0e578c6f9 100644 --- a/pkg/fuzzer/queue/queue.go +++ b/pkg/fuzzer/queue/queue.go @@ -135,7 +135,7 @@ func (r *Request) initChannel() { } type Result struct { - Info *ipc.ProgInfo + Info *flatrpc.ProgInfo Output []byte Status Status Err error // More details in case of ExecFailure. @@ -143,9 +143,7 @@ type Result struct { func (r *Result) clone() *Result { ret := *r - if ret.Info != nil { - ret.Info = ret.Info.Clone() - } + ret.Info = ret.Info.Clone() return &ret } diff --git a/pkg/ipc/ipc.go b/pkg/ipc/ipc.go index 0e12fa2bd..9b4f77d66 100644 --- a/pkg/ipc/ipc.go +++ b/pkg/ipc/ipc.go @@ -6,14 +6,12 @@ package ipc import ( "fmt" "io" - "maps" "os" "os/exec" "path/filepath" "slices" "strings" "sync" - "syscall" "time" "unsafe" @@ -53,60 +51,6 @@ type Config struct { Timeouts targets.Timeouts } -type CallFlags uint32 - -const ( - CallExecuted CallFlags = 1 << iota // was started at all - CallFinished // finished executing (rather than blocked forever) - CallBlocked // finished but blocked during execution - CallFaultInjected // fault was injected into this call -) - -type CallInfo struct { - Flags CallFlags - Signal []uint32 // feedback signal, filled if FlagSignal is set - Cover []uint32 // per-call coverage, filled if FlagSignal is set and cover == true, - // if dedup == false, then cov effectively contains a trace, otherwise duplicates are removed - Comps prog.CompMap // per-call comparison operands - Errno int // call errno (0 if the call was successful) -} - -func (ci *CallInfo) Clone() CallInfo { - ret := *ci - ret.Signal = slices.Clone(ret.Signal) - ret.Cover = slices.Clone(ret.Cover) - ret.Comps = maps.Clone(ret.Comps) - return ret -} - -type ProgInfo struct { - Calls []CallInfo - Extra CallInfo // stores Signal and Cover collected from background threads - Elapsed time.Duration // total execution time of the program - Freshness int // number of programs executed in the same process before this one -} - -func (pi *ProgInfo) Clone() *ProgInfo { - ret := *pi - ret.Extra = ret.Extra.Clone() - ret.Calls = slices.Clone(ret.Calls) - for i, call := range ret.Calls { - ret.Calls[i] = call.Clone() - } - return &ret -} - -func EmptyProgInfo(calls int) *ProgInfo { - info := &ProgInfo{Calls: make([]CallInfo, calls)} - for i := range info.Calls { - // Store some unsuccessful errno in the case we won't get any result. - // It also won't have CallExecuted flag, but it's handy to make it - // look failed based on errno as well. - info.Calls[i].Errno = int(syscall.ENOSYS) - } - return info -} - type Env struct { in []byte out []byte @@ -312,7 +256,8 @@ func (env *Env) Close() error { // info: per-call info // hanged: program hanged and was killed // err0: failed to start the process or bug in executor itself. -func (env *Env) ExecProg(opts *ExecOpts, progData []byte) (output []byte, info *ProgInfo, hanged bool, err0 error) { +func (env *Env) ExecProg(opts *ExecOpts, progData []byte) ( + output []byte, info *flatrpc.ProgInfo, hanged bool, err0 error) { ncalls, err := prog.ExecCallCount(progData) if err != nil { err0 = err @@ -345,7 +290,7 @@ func (env *Env) ExecProg(opts *ExecOpts, progData []byte) (output []byte, info * info, err0 = env.parseOutput(opts, ncalls) if info != nil { - info.Elapsed = elapsed + info.Elapsed = uint64(elapsed) info.Freshness = env.cmd.freshness } env.cmd.freshness++ @@ -356,7 +301,7 @@ func (env *Env) ExecProg(opts *ExecOpts, progData []byte) (output []byte, info * return } -func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *ProgInfo, hanged bool, err0 error) { +func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *flatrpc.ProgInfo, hanged bool, err0 error) { progData, err := p.SerializeForExec() if err != nil { err0 = err @@ -396,21 +341,21 @@ var ( rateLimiter <-chan time.Time ) -func (env *Env) parseOutput(opts *ExecOpts, ncalls int) (*ProgInfo, error) { +func (env *Env) parseOutput(opts *ExecOpts, ncalls int) (*flatrpc.ProgInfo, error) { out := env.out ncmd, ok := readUint32(&out) if !ok { return nil, fmt.Errorf("failed to read number of calls") } - info := EmptyProgInfo(ncalls) - extraParts := make([]CallInfo, 0) + info := flatrpc.EmptyProgInfo(ncalls) + extraParts := make([]flatrpc.CallInfo, 0) for i := uint32(0); i < ncmd; i++ { if len(out) < int(unsafe.Sizeof(callReply{})) { return nil, fmt.Errorf("failed to read call %v reply", i) } reply := *(*callReply)(unsafe.Pointer(&out[0])) out = out[unsafe.Sizeof(callReply{}):] - var inf *CallInfo + var inf *flatrpc.CallInfo if reply.magic != outMagic { return nil, fmt.Errorf("bad reply magic 0x%x", reply.magic) } @@ -418,14 +363,14 @@ func (env *Env) parseOutput(opts *ExecOpts, ncalls int) (*ProgInfo, error) { if int(reply.index) >= len(info.Calls) { return nil, fmt.Errorf("bad call %v index %v/%v", i, reply.index, len(info.Calls)) } - inf = &info.Calls[reply.index] + inf = info.Calls[reply.index] if inf.Flags != 0 || inf.Signal != nil { return nil, fmt.Errorf("duplicate reply for call %v/%v/%v", i, reply.index, reply.num) } - inf.Errno = int(reply.errno) - inf.Flags = CallFlags(reply.flags) + inf.Error = int32(reply.errno) + inf.Flags = flatrpc.CallFlag(reply.flags) } else { - extraParts = append(extraParts, CallInfo{}) + extraParts = append(extraParts, flatrpc.CallInfo{}) inf = &extraParts[len(extraParts)-1] } if inf.Signal, ok = readUint32Array(&out, reply.signalSize); !ok { @@ -449,8 +394,8 @@ func (env *Env) parseOutput(opts *ExecOpts, ncalls int) (*ProgInfo, error) { return info, nil } -func convertExtra(extraParts []CallInfo, dedupCover bool) CallInfo { - var extra CallInfo +func convertExtra(extraParts []flatrpc.CallInfo, dedupCover bool) *flatrpc.CallInfo { + var extra flatrpc.CallInfo if dedupCover { extraCover := make(cover.Cover) for _, part := range extraParts { @@ -472,14 +417,11 @@ func convertExtra(extraParts []CallInfo, dedupCover bool) CallInfo { extra.Signal[i] = uint32(s) i++ } - return extra + return &extra } -func readComps(outp *[]byte, compsSize uint32) (prog.CompMap, error) { - if compsSize == 0 { - return nil, nil - } - compMap := make(prog.CompMap) +func readComps(outp *[]byte, compsSize uint32) ([]*flatrpc.Comparison, error) { + comps := make([]*flatrpc.Comparison, 0, 2*compsSize) for i := uint32(0); i < compsSize; i++ { typ, ok := readUint32(outp) if !ok { @@ -505,7 +447,7 @@ func readComps(outp *[]byte, compsSize uint32) (prog.CompMap, error) { if op1 == op2 { continue // it's useless to store such comparisons } - compMap.AddComp(op2, op1) + comps = append(comps, &flatrpc.Comparison{Op1: op2, Op2: op1}) if (typ & compConstMask) != 0 { // If one of the operands was const, then this operand is always // placed first in the instrumented callbacks. Such an operand @@ -513,9 +455,9 @@ func readComps(outp *[]byte, compsSize uint32) (prog.CompMap, error) { // it wouldn't be const), thus we simply ignore it. continue } - compMap.AddComp(op1, op2) + comps = append(comps, &flatrpc.Comparison{Op1: op1, Op2: op2}) } - return compMap, nil + return comps, nil } func readUint32(outp *[]byte) (uint32, bool) { @@ -567,7 +509,7 @@ type command struct { inrp *os.File outwp *os.File outmem []byte - freshness int + freshness uint64 } const ( diff --git a/pkg/ipc/ipc_test.go b/pkg/ipc/ipc_test.go index 30e97660f..af9557e1b 100644 --- a/pkg/ipc/ipc_test.go +++ b/pkg/ipc/ipc_test.go @@ -111,8 +111,8 @@ func TestExecute(t *testing.T) { if len(info.Calls) != len(p.Calls) { t.Fatalf("executed less calls (%v) than prog len(%v):\n%s", len(info.Calls), len(p.Calls), output) } - if info.Calls[0].Errno != 0 { - t.Fatalf("simple call failed: %v\n%s", info.Calls[0].Errno, output) + if info.Calls[0].Error != 0 { + t.Fatalf("simple call failed: %v\n%s", info.Calls[0].Error, output) } if len(output) != 0 { t.Fatalf("output on empty program") @@ -159,8 +159,8 @@ func TestParallel(t *testing.T) { err = fmt.Errorf("no calls executed:\n%s", output) return } - if info.Calls[0].Errno != 0 { - err = fmt.Errorf("simple call failed: %v\n%s", info.Calls[0].Errno, output) + if info.Calls[0].Error != 0 { + err = fmt.Errorf("simple call failed: %v\n%s", info.Calls[0].Error, output) return } if len(output) != 0 { @@ -211,8 +211,8 @@ func TestZlib(t *testing.T) { if err != nil { t.Fatalf("failed to run executor: %v", err) } - if info.Calls[0].Errno != 0 { - t.Fatalf("data comparison failed: %v\n%s", info.Calls[0].Errno, output) + if info.Calls[0].Error != 0 { + t.Fatalf("data comparison failed: %v\n%s", info.Calls[0].Error, output) } } } @@ -258,7 +258,7 @@ func TestExecutorCommonExt(t *testing.T) { if err != nil { t.Fatal(err) } - if call := info.Calls[0]; (call.Flags&CallFinished) == 0 || call.Errno != 0 { - t.Fatalf("bad call result: flags=%x errno=%v", call.Flags, call.Errno) + if call := info.Calls[0]; call.Flags&flatrpc.CallFlagFinished == 0 || call.Error != 0 { + t.Fatalf("bad call result: flags=%x errno=%v", call.Flags, call.Error) } } diff --git a/pkg/rpctype/rpctype.go b/pkg/rpctype/rpctype.go index 89ff419c1..e314424ea 100644 --- a/pkg/rpctype/rpctype.go +++ b/pkg/rpctype/rpctype.go @@ -2,166 +2,9 @@ // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. // Package rpctype contains types of message passed via net/rpc connections -// between various parts of the system. +// between syz-manager and syz-hub. package rpctype -import ( - "math" - "time" - - "github.com/google/syzkaller/pkg/flatrpc" - "github.com/google/syzkaller/pkg/ipc" - "github.com/google/syzkaller/pkg/signal" -) - -// ExecutionRequest describes the task of executing a particular program. -// Corresponds to Fuzzer.Request. -type ExecutionRequest struct { - ID int64 - ProgData []byte - ExecOpts ipc.ExecOpts - NewSignal bool - // If set, ProgData contains compiled executable binary - // that needs to be written to disk and executed. - IsBinary bool - // If set, fully reset executor state befor executing the test. - ResetState bool - // If set, collect program output and return in ExecutionResult.Output. - ReturnOutput bool - // If set, don't fail on program failures, instead return the error in ExecutionResult.Error. - ReturnError bool - SignalFilter signal.Signal - SignalFilterCall int - // Repeat the program that many times (0 means 1). - Repeat int -} - -// ExecutionResult is sent after ExecutionRequest is completed. -type ExecutionResult struct { - ID int64 - ProcID int - Try int - Info ipc.ProgInfo - Output []byte - Error string -} - -// ExchangeInfoRequest is periodically sent by syz-fuzzer to syz-manager. -type ExchangeInfoRequest struct { - Name string - NeedProgs int - StatsDelta map[string]uint64 - Results []ExecutionResult - Latency time.Duration // latency of the previous ExchangeInfo request -} - -// ExchangeInfoReply is a reply to ExchangeInfoRequest. -type ExchangeInfoReply struct { - Requests []ExecutionRequest - NewMaxSignal []uint32 - DropMaxSignal []uint32 -} - -// ExecutingRequest is notification from the fuzzer that it started executing -// the program ProgID. We want this request to be as small and as fast as possible -// b/c we want it to reach manager (or at least leave the VM) before it crashes -// executing this program. -type ExecutingRequest struct { - Name string - ID int64 - ProcID int - Try int -} - -// TODO: merge ExecutionRequest and ExecTask. -type ExecTask struct { - Prog []byte - ID int64 -} - -type ConnectArgs struct { - Name string - GitRevision string - SyzRevision string - ExecutorArch string - ExecutorGitRevision string - ExecutorSyzRevision string -} - -type ConnectRes struct { - MemoryLeakFrames []string - DataRaceFrames []string - // Bitmask of features to try to setup. - Features flatrpc.Feature - // Fuzzer reads these files inside of the VM and returns contents in CheckArgs.Files. - ReadFiles []string - ReadGlobs []string -} - -type CheckArgs struct { - Name string - Error string - Features []*flatrpc.FeatureInfo - Globs map[string][]string - Files []*flatrpc.FileInfo -} - -type CheckRes struct { - CoverFilterBitmap []byte -} - -type SyscallReason struct { - ID int - Reason string -} - -type RunnerConnectArgs struct { - Pool, VM int -} - -type RunnerConnectRes struct { - // CheckUnsupportedCalls is set to true if the Runner needs to query the kernel - // for unsupported system calls and report them back to the server. - CheckUnsupportedCalls bool -} - -// UpdateUnsupportedArgs contains the data passed from client to server in an -// UpdateSupported call, namely the system calls not supported by the client's -// kernel. -type UpdateUnsupportedArgs struct { - // Pool is used to identify the checked kernel. - Pool int - // UnsupportedCalls contains the ID's of system calls not supported by the - // client and the reason for this. - UnsupportedCalls []SyscallReason -} - -// NextExchangeArgs contains the data passed from client to server namely -// identification information of the VM and program execution results. -type NextExchangeArgs struct { - // Pool/VM are used to identify the instance on which the client is running. - Pool, VM int - // ExecTaskID is used to uniquely identify the program for which the client is - // sending results. - ExecTaskID int64 - // Hanged is set to true if the program for which we are sending results - // was killed due to hanging. - Hanged bool - // Info contains information about the execution of each system call in the - // program. - Info ipc.ProgInfo -} - -// NextExchaneRes contains the data passed from server to client namely -// programs to execute on the VM. -type NextExchangeRes struct { - ExecTask -} - -const ( - NoTask int64 = math.MaxInt64 -) - type HubConnectArgs struct { // Client/Key are used for authentication. Client string diff --git a/pkg/runtest/run.go b/pkg/runtest/run.go index 29fa9d0cf..2c6a60d4a 100644 --- a/pkg/runtest/run.go +++ b/pkg/runtest/run.go @@ -38,7 +38,7 @@ type runRequest struct { err error result *queue.Result - results *ipc.ProgInfo // the expected results + results *flatrpc.ProgInfo // the expected results name string broken string @@ -291,7 +291,7 @@ nextSandbox: return nil } -func parseProg(target *prog.Target, dir, filename string) (*prog.Prog, map[string]bool, *ipc.ProgInfo, error) { +func parseProg(target *prog.Target, dir, filename string) (*prog.Prog, map[string]bool, *flatrpc.ProgInfo, error) { data, err := os.ReadFile(filepath.Join(dir, filename)) if err != nil { return nil, nil, nil, fmt.Errorf("failed to read %v: %w", filename, err) @@ -306,7 +306,7 @@ func parseProg(target *prog.Target, dir, filename string) (*prog.Prog, map[strin if err != nil { return nil, nil, nil, fmt.Errorf("failed to deserialize %v: %w", filename, err) } - errnos := map[string]int{ + errnos := map[string]int32{ "": 0, "EPERM": 1, "ENOENT": 2, @@ -332,24 +332,27 @@ func parseProg(target *prog.Target, dir, filename string) (*prog.Prog, map[strin "ZX_ERR_ALREADY_EXISTS": 26, "ZX_ERR_ACCESS_DENIED": 30, } - info := &ipc.ProgInfo{Calls: make([]ipc.CallInfo, len(p.Calls))} - for i, call := range p.Calls { - info.Calls[i].Flags |= ipc.CallExecuted | ipc.CallFinished + info := &flatrpc.ProgInfo{} + for _, call := range p.Calls { + ci := &flatrpc.CallInfo{ + Flags: flatrpc.CallFlagExecuted | flatrpc.CallFlagFinished, + } switch call.Comment { case "blocked": - info.Calls[i].Flags |= ipc.CallBlocked + ci.Flags |= flatrpc.CallFlagBlocked case "unfinished": - info.Calls[i].Flags &^= ipc.CallFinished + ci.Flags &^= flatrpc.CallFlagFinished case "unexecuted": - info.Calls[i].Flags &^= ipc.CallExecuted | ipc.CallFinished + ci.Flags &^= flatrpc.CallFlagExecuted | flatrpc.CallFlagFinished default: res, ok := errnos[call.Comment] if !ok { return nil, nil, nil, fmt.Errorf("%v: unknown call comment %q", filename, call.Comment) } - info.Calls[i].Errno = res + ci.Error = res } + info.Calls = append(info.Calls, ci) } return p, requires, info, nil } @@ -386,7 +389,7 @@ func checkArch(requires map[string]bool, arch string) bool { } func (ctx *Context) produceTest(progs chan *runRequest, req *runRequest, name string, - properties, requires map[string]bool, results *ipc.ProgInfo) { + properties, requires map[string]bool, results *flatrpc.ProgInfo) { req.name = name req.results = results if !match(properties, requires) { @@ -505,7 +508,7 @@ func checkResult(req *runRequest) error { if req.result.Status != queue.Success { return fmt.Errorf("non-successful result status (%v)", req.result.Status) } - var infos []ipc.ProgInfo + var infos []*flatrpc.ProgInfo isC := req.BinaryFile != "" if isC { var err error @@ -516,7 +519,7 @@ func checkResult(req *runRequest) error { raw := req.result.Info for len(raw.Calls) != 0 { ncalls := min(len(raw.Calls), len(req.Prog.Calls)) - infos = append(infos, ipc.ProgInfo{ + infos = append(infos, &flatrpc.ProgInfo{ Extra: raw.Extra, Calls: raw.Calls[:ncalls], }) @@ -538,15 +541,11 @@ func checkResult(req *runRequest) error { return nil } -func checkCallResult(req *runRequest, isC bool, run, call int, info ipc.ProgInfo, calls map[string]bool) error { +func checkCallResult(req *runRequest, isC bool, run, call int, info *flatrpc.ProgInfo, calls map[string]bool) error { inf := info.Calls[call] want := req.results.Calls[call] - for flag, what := range map[ipc.CallFlags]string{ - ipc.CallExecuted: "executed", - ipc.CallBlocked: "blocked", - ipc.CallFinished: "finished", - } { - if flag != ipc.CallFinished { + for flag, what := range flatrpc.EnumNamesCallFlag { + if flag != flatrpc.CallFlagFinished { if isC { // C code does not detect blocked/non-finished calls. continue @@ -557,7 +556,7 @@ func checkCallResult(req *runRequest, isC bool, run, call int, info ipc.ProgInfo continue } } - if runtime.GOOS == targets.FreeBSD && flag == ipc.CallBlocked { + if runtime.GOOS == targets.FreeBSD && flag == flatrpc.CallFlagBlocked { // Blocking detection is flaky on freebsd. // TODO(dvyukov): try to increase the timeout in executor to make it non-flaky. continue @@ -570,11 +569,11 @@ func checkCallResult(req *runRequest, isC bool, run, call int, info ipc.ProgInfo return fmt.Errorf("run %v: call %v is%v %v", run, call, not, what) } } - if inf.Flags&ipc.CallFinished != 0 && inf.Errno != want.Errno { + if inf.Flags&flatrpc.CallFlagFinished != 0 && inf.Error != want.Error { return fmt.Errorf("run %v: wrong call %v result %v, want %v", - run, call, inf.Errno, want.Errno) + run, call, inf.Error, want.Error) } - if isC || inf.Flags&ipc.CallExecuted == 0 { + if isC || inf.Flags&flatrpc.CallFlagExecuted == 0 { return nil } if req.ExecOpts.EnvFlags&flatrpc.ExecEnvSignal != 0 { @@ -600,13 +599,17 @@ func checkCallResult(req *runRequest, isC bool, run, call int, info ipc.ProgInfo return nil } -func parseBinOutput(req *runRequest) ([]ipc.ProgInfo, error) { - var infos []ipc.ProgInfo +func parseBinOutput(req *runRequest) ([]*flatrpc.ProgInfo, error) { + var infos []*flatrpc.ProgInfo s := bufio.NewScanner(bytes.NewReader(req.result.Output)) re := regexp.MustCompile("^### call=([0-9]+) errno=([0-9]+)$") for s.Scan() { if s.Text() == "### start" { - infos = append(infos, ipc.ProgInfo{Calls: make([]ipc.CallInfo, len(req.Prog.Calls))}) + pi := &flatrpc.ProgInfo{} + for range req.Prog.Calls { + pi.Calls = append(pi.Calls, &flatrpc.CallInfo{}) + } + infos = append(infos, pi) } match := re.FindSubmatch(s.Bytes()) if match == nil { @@ -625,15 +628,15 @@ func parseBinOutput(req *runRequest) ([]ipc.ProgInfo, error) { return nil, fmt.Errorf("failed to parse errno %q in %q", string(match[2]), s.Text()) } - info := &infos[len(infos)-1] + info := infos[len(infos)-1] if call >= uint64(len(info.Calls)) { return nil, fmt.Errorf("bad call index %v", call) } if info.Calls[call].Flags != 0 { return nil, fmt.Errorf("double result for call %v", call) } - info.Calls[call].Flags |= ipc.CallExecuted | ipc.CallFinished - info.Calls[call].Errno = int(errno) + info.Calls[call].Flags |= flatrpc.CallFlagExecuted | flatrpc.CallFlagFinished + info.Calls[call].Error = int32(errno) } return infos, nil } diff --git a/pkg/vminfo/features.go b/pkg/vminfo/features.go index 3b7bae8d5..905fc630f 100644 --- a/pkg/vminfo/features.go +++ b/pkg/vminfo/features.go @@ -186,8 +186,8 @@ func (ctx *checkContext) featureSucceeded(feat flatrpc.Feature, testProg *prog.P len(res.Info.Calls), len(testProg.Calls)) } for i, call := range res.Info.Calls { - if call.Errno != 0 { - return fmt.Sprintf("call %v failed with errno %v", i, call.Errno) + if call.Error != 0 { + return fmt.Sprintf("call %v failed with errno %v", i, call.Error) } } call := res.Info.Calls[0] diff --git a/pkg/vminfo/syscalls.go b/pkg/vminfo/syscalls.go index f6ab24a04..23c9504e2 100644 --- a/pkg/vminfo/syscalls.go +++ b/pkg/vminfo/syscalls.go @@ -140,7 +140,7 @@ func (ctx *checkContext) canOpenImpl(file string, modes []uint64, root bool) str } info := ctx.execRaw(calls, prog.StrictUnsafe, root) for _, call := range info.Calls { - if call.Errno == 0 { + if call.Error == 0 { return "" } } @@ -148,7 +148,7 @@ func (ctx *checkContext) canOpenImpl(file string, modes []uint64, root bool) str if root { who = "root " } - return fmt.Sprintf("%vfailed to open %s: %v", who, file, syscall.Errno(info.Calls[0].Errno)) + return fmt.Sprintf("%vfailed to open %s: %v", who, file, syscall.Errno(info.Calls[0].Error)) } func (ctx *checkContext) supportedSyscalls(names []string) string { @@ -161,7 +161,7 @@ func (ctx *checkContext) supportedSyscalls(names []string) string { } info := ctx.execRaw(calls, prog.NonStrictUnsafe, false) for i, res := range info.Calls { - if res.Errno == int(syscall.ENOSYS) { + if res.Error == int32(syscall.ENOSYS) { return fmt.Sprintf("syscall %v is not present", names[i]) } } @@ -201,17 +201,17 @@ func (ctx *checkContext) callSucceeds(call string) string { func (ctx *checkContext) execCall(call string) syscall.Errno { info := ctx.execRaw([]string{call}, prog.StrictUnsafe, false) - return syscall.Errno(info.Calls[0].Errno) + return syscall.Errno(info.Calls[0].Error) } func (ctx *checkContext) anyCallSucceeds(calls []string, msg string) string { info := ctx.execRaw(calls, prog.StrictUnsafe, false) for _, call := range info.Calls { - if call.Errno == 0 { + if call.Error == 0 { return "" } } - return fmt.Sprintf("%s: %v", msg, syscall.Errno(info.Calls[0].Errno)) + return fmt.Sprintf("%s: %v", msg, syscall.Errno(info.Calls[0].Error)) } func (ctx *checkContext) onlySandboxNone() string { @@ -236,12 +236,12 @@ func (ctx *checkContext) val(name string) uint64 { return val } -func (ctx *checkContext) execRaw(calls []string, mode prog.DeserializeMode, root bool) *ipc.ProgInfo { +func (ctx *checkContext) execRaw(calls []string, mode prog.DeserializeMode, root bool) *flatrpc.ProgInfo { sandbox := ctx.sandbox if root { sandbox = 0 } - info := &ipc.ProgInfo{} + info := &flatrpc.ProgInfo{} for remain := calls; len(remain) != 0; { // Don't put too many syscalls into a single program, // it will have higher chances to time out. @@ -267,7 +267,7 @@ func (ctx *checkContext) execRaw(calls []string, mode prog.DeserializeMode, root info.Calls = append(info.Calls, res.Info.Calls...) } else if res.Status == queue.Crashed { // Pretend these calls were not executed. - info.Calls = append(info.Calls, ipc.EmptyProgInfo(ncalls).Calls...) + info.Calls = append(info.Calls, flatrpc.EmptyProgInfo(ncalls).Calls...) } else { // The program must have been either executed or not due to a crash. panic(fmt.Sprintf("got unexpected execution status (%d) for the prog %s", diff --git a/pkg/vminfo/vminfo_test.go b/pkg/vminfo/vminfo_test.go index b73a6ad66..0e5d17ef2 100644 --- a/pkg/vminfo/vminfo_test.go +++ b/pkg/vminfo/vminfo_test.go @@ -103,14 +103,12 @@ func createSuccessfulResults(source queue.Source, stop chan struct{}) { // Currently we have 641 (when we failed to properly dedup syscall tests, it was 4349). panic("too many test programs") } - info := &ipc.ProgInfo{} + info := &flatrpc.ProgInfo{} for range req.Prog.Calls { - info.Calls = append(info.Calls, ipc.CallInfo{ + info.Calls = append(info.Calls, &flatrpc.CallInfo{ Cover: []uint32{1}, Signal: []uint32{1}, - Comps: map[uint64]map[uint64]bool{ - 1: {2: true}, - }, + Comps: []*flatrpc.Comparison{{Op1: 1, Op2: 2}}, }) } req.Done(&queue.Result{ diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go index 5feae7585..fbc00feeb 100644 --- a/syz-fuzzer/fuzzer.go +++ b/syz-fuzzer/fuzzer.go @@ -268,7 +268,9 @@ func (tool *FuzzerTool) diffMaxSignal(info *flatrpc.ProgInfo, mask signal.Signal } func diffMaxSignal(info *flatrpc.ProgInfo, max, mask signal.Signal, maskCall int) { - info.Extra.Signal = diffCallSignal(info.Extra.Signal, max, mask, -1, maskCall) + if info.Extra != nil { + info.Extra.Signal = diffCallSignal(info.Extra.Signal, max, mask, -1, maskCall) + } for i := 0; i < len(info.Calls); i++ { info.Calls[i].Signal = diffCallSignal(info.Calls[i].Signal, max, mask, i, maskCall) } diff --git a/syz-fuzzer/proc.go b/syz-fuzzer/proc.go index acc333b9b..c243c8a31 100644 --- a/syz-fuzzer/proc.go +++ b/syz-fuzzer/proc.go @@ -52,7 +52,7 @@ func (proc *Proc) loop() { info, output, err := proc.execute(req, wait) res := &flatrpc.ExecResult{ Id: req.Id, - Info: convertProgInfo(info), + Info: info, Output: output, Error: err, } @@ -63,9 +63,9 @@ func (proc *Proc) loop() { } info, output, err := proc.execute(req, 0) if res.Info == nil { - res.Info = convertProgInfo(info) + res.Info = info } else if info != nil { - res.Info.Calls = append(res.Info.Calls, convertCalls(info)...) + res.Info.Calls = append(res.Info.Calls, info.Calls...) } res.Output = append(res.Output, output...) res.Error = err @@ -101,7 +101,7 @@ func (proc *Proc) nextRequest() (*flatrpc.ExecRequest, time.Duration) { } func (proc *Proc) execute(req *flatrpc.ExecRequest, wait time.Duration) ( - info *ipc.ProgInfo, output []byte, errStr string) { + info *flatrpc.ProgInfo, output []byte, errStr string) { var err error if req.Flags&flatrpc.RequestFlagIsBinary != 0 { output, err = executeBinary(req) @@ -117,7 +117,7 @@ func (proc *Proc) execute(req *flatrpc.ExecRequest, wait time.Duration) ( return } -func (proc *Proc) executeProgram(req *flatrpc.ExecRequest, wait time.Duration) (*ipc.ProgInfo, []byte, error) { +func (proc *Proc) executeProgram(req *flatrpc.ExecRequest, wait time.Duration) (*flatrpc.ProgInfo, []byte, error) { returnError := req.Flags&flatrpc.RequestFlagReturnError != 0 execOpts := &ipc.ExecOpts{ EnvFlags: req.ExecEnv, @@ -126,7 +126,7 @@ func (proc *Proc) executeProgram(req *flatrpc.ExecRequest, wait time.Duration) ( } for try := 0; ; try++ { var output []byte - var info *ipc.ProgInfo + var info *flatrpc.ProgInfo var hanged bool // On a heavily loaded VM, syz-executor may take significant time to start. // Let's do it outside of the gate ticket. @@ -180,39 +180,3 @@ func executeBinary(req *flatrpc.ExecRequest) ([]byte, error) { } return output, err } - -func convertProgInfo(info *ipc.ProgInfo) *flatrpc.ProgInfo { - if info == nil { - return nil - } - return &flatrpc.ProgInfo{ - Elapsed: uint64(info.Elapsed), - Freshness: uint64(info.Freshness), - Extra: convertCallInfo(info.Extra), - Calls: convertCalls(info), - } -} - -func convertCalls(info *ipc.ProgInfo) []*flatrpc.CallInfo { - var calls []*flatrpc.CallInfo - for _, call := range info.Calls { - calls = append(calls, convertCallInfo(call)) - } - return calls -} - -func convertCallInfo(info ipc.CallInfo) *flatrpc.CallInfo { - var comps []*flatrpc.Comparison - for op1, ops := range info.Comps { - for op2 := range ops { - comps = append(comps, &flatrpc.Comparison{Op1: op1, Op2: op2}) - } - } - return &flatrpc.CallInfo{ - Flags: flatrpc.CallFlag(info.Flags), - Error: int32(info.Errno), - Cover: info.Cover, - Signal: info.Signal, - Comps: comps, - } -} diff --git a/syz-fuzzer/testing.go b/syz-fuzzer/testing.go index 100f63fad..e22813d2a 100644 --- a/syz-fuzzer/testing.go +++ b/syz-fuzzer/testing.go @@ -111,7 +111,7 @@ func checkSimpleProgram(args *checkArgs) error { if len(info.Calls) == 0 { return fmt.Errorf("no calls executed:\n%s", output) } - if info.Calls[0].Errno != 0 { + if info.Calls[0].Error != 0 { return fmt.Errorf("simple call failed: %+v\n%s", info.Calls[0], output) } if args.ipcExecOpts.EnvFlags&flatrpc.ExecEnvSignal != 0 && len(info.Calls[0].Signal) < 2 { diff --git a/syz-manager/rpc.go b/syz-manager/rpc.go index 2f26ac4c2..711c0a6a4 100644 --- a/syz-manager/rpc.go +++ b/syz-manager/rpc.go @@ -383,8 +383,10 @@ func (serv *RPCServer) handleExecResult(runner *Runner, msg *flatrpc.ExecResult) call.Cover = runner.canonicalizer.Canonicalize(call.Cover) call.Signal = runner.canonicalizer.Canonicalize(call.Signal) } - msg.Info.Extra.Cover = runner.canonicalizer.Canonicalize(msg.Info.Extra.Cover) - msg.Info.Extra.Signal = runner.canonicalizer.Canonicalize(msg.Info.Extra.Signal) + if msg.Info.Extra != nil { + msg.Info.Extra.Cover = runner.canonicalizer.Canonicalize(msg.Info.Extra.Cover) + msg.Info.Extra.Signal = runner.canonicalizer.Canonicalize(msg.Info.Extra.Signal) + } } status := queue.Success var resErr error @@ -394,7 +396,7 @@ func (serv *RPCServer) handleExecResult(runner *Runner, msg *flatrpc.ExecResult) } req.Done(&queue.Result{ Status: status, - Info: convertProgInfo(msg.Info), + Info: msg.Info, Output: slices.Clone(msg.Output), Err: resErr, }) @@ -623,37 +625,3 @@ func addFallbackSignal(p *prog.Prog, info *flatrpc.ProgInfo) { info.Calls[i].Signal = inf.Signal } } - -func convertProgInfo(info *flatrpc.ProgInfo) *ipc.ProgInfo { - if info == nil { - return nil - } - return &ipc.ProgInfo{ - Elapsed: time.Duration(info.Elapsed), - Freshness: int(info.Freshness), - Extra: convertCallInfo(info.Extra), - Calls: convertCalls(info), - } -} - -func convertCalls(info *flatrpc.ProgInfo) []ipc.CallInfo { - var calls []ipc.CallInfo - for _, call := range info.Calls { - calls = append(calls, convertCallInfo(call)) - } - return calls -} - -func convertCallInfo(info *flatrpc.CallInfo) ipc.CallInfo { - comps := make(prog.CompMap) - for _, comp := range info.Comps { - comps.AddComp(comp.Op1, comp.Op2) - } - return ipc.CallInfo{ - Flags: ipc.CallFlags(info.Flags), - Errno: int(info.Error), - Cover: info.Cover, - Signal: info.Signal, - Comps: comps, - } -} diff --git a/syz-runner/runner.go b/syz-runner/runner.go index 8c9f3a5c3..5a9248611 100644 --- a/syz-runner/runner.go +++ b/syz-runner/runner.go @@ -1,5 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/execresult.go b/syz-verifier/execresult.go index 9db053a35..dcf2f5812 100644 --- a/syz-verifier/execresult.go +++ b/syz-verifier/execresult.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/execresult_test.go b/syz-verifier/execresult_test.go index 1ff25e73d..af82130d8 100644 --- a/syz-verifier/execresult_test.go +++ b/syz-verifier/execresult_test.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/exectask.go b/syz-verifier/exectask.go index 77ccf1cb5..2e47069c3 100644 --- a/syz-verifier/exectask.go +++ b/syz-verifier/exectask.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/exectask_test.go b/syz-verifier/exectask_test.go index b8e73a587..043cbcd63 100644 --- a/syz-verifier/exectask_test.go +++ b/syz-verifier/exectask_test.go @@ -1,6 +1,10 @@ // Copyright 2022 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/main.go b/syz-verifier/main.go index 7e58cd0fe..2ae5894e5 100755 --- a/syz-verifier/main.go +++ b/syz-verifier/main.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + // package main starts the syz-verifier tool. High-level documentation can be // found in docs/syz_verifier.md. package main diff --git a/syz-verifier/main_test.go b/syz-verifier/main_test.go deleted file mode 100644 index 197daa285..000000000 --- a/syz-verifier/main_test.go +++ /dev/null @@ -1,3 +0,0 @@ -// Copyright 2021 syzkaller project authors. All rights reserved. -// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. -package main diff --git a/syz-verifier/monitoring_api.go b/syz-verifier/monitoring_api.go index 50cef162b..51d373f2f 100644 --- a/syz-verifier/monitoring_api.go +++ b/syz-verifier/monitoring_api.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/rpcserver.go b/syz-verifier/rpcserver.go index f80fb7a46..66f15421b 100644 --- a/syz-verifier/rpcserver.go +++ b/syz-verifier/rpcserver.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/rpcserver_test.go b/syz-verifier/rpcserver_test.go index 71047fd2f..a31056a8a 100644 --- a/syz-verifier/rpcserver_test.go +++ b/syz-verifier/rpcserver_test.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/stats.go b/syz-verifier/stats.go index 41ffb7848..22d732034 100644 --- a/syz-verifier/stats.go +++ b/syz-verifier/stats.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/stats_test.go b/syz-verifier/stats_test.go index 762f9092c..b569f0965 100644 --- a/syz-verifier/stats_test.go +++ b/syz-verifier/stats_test.go @@ -1,5 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/utils_test.go b/syz-verifier/utils_test.go index 36bec3f74..deaada1b9 100644 --- a/syz-verifier/utils_test.go +++ b/syz-verifier/utils_test.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/verifier.go b/syz-verifier/verifier.go index 295a9da93..c9ca38512 100644 --- a/syz-verifier/verifier.go +++ b/syz-verifier/verifier.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/syz-verifier/verifier_test.go b/syz-verifier/verifier_test.go index bf3ba719d..5dd689421 100644 --- a/syz-verifier/verifier_test.go +++ b/syz-verifier/verifier_test.go @@ -1,6 +1,10 @@ // Copyright 2021 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: switch syz-verifier to use syz-fuzzer. + +//go:build never + package main import ( diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go index fdeee6cef..066c1f4ee 100644 --- a/tools/syz-execprog/execprog.go +++ b/tools/syz-execprog/execprog.go @@ -251,43 +251,40 @@ func (ctx *Context) logProgram(pid int, p *prog.Prog, callOpts *ipc.ExecOpts) { ctx.logMu.Unlock() } -func (ctx *Context) printCallResults(info *ipc.ProgInfo) { +func (ctx *Context) printCallResults(info *flatrpc.ProgInfo) { for i, inf := range info.Calls { - if inf.Flags&ipc.CallExecuted == 0 { + if inf.Flags&flatrpc.CallFlagExecuted == 0 { continue } flags := "" - if inf.Flags&ipc.CallFinished == 0 { + if inf.Flags&flatrpc.CallFlagFinished == 0 { flags += " unfinished" } - if inf.Flags&ipc.CallBlocked != 0 { + if inf.Flags&flatrpc.CallFlagBlocked != 0 { flags += " blocked" } - if inf.Flags&ipc.CallFaultInjected != 0 { + if inf.Flags&flatrpc.CallFlagFaultInjected != 0 { flags += " faulted" } log.Logf(1, "CALL %v: signal %v, coverage %v errno %v%v", - i, len(inf.Signal), len(inf.Cover), inf.Errno, flags) + i, len(inf.Signal), len(inf.Cover), inf.Error, flags) } } -func (ctx *Context) printHints(p *prog.Prog, info *ipc.ProgInfo) { +func (ctx *Context) printHints(p *prog.Prog, info *flatrpc.ProgInfo) { ncomps, ncandidates := 0, 0 for i := range p.Calls { if *flagOutput { fmt.Printf("call %v:\n", i) } - comps := info.Calls[i].Comps - for v, args := range comps { - ncomps += len(args) + comps := make(prog.CompMap) + for _, cmp := range info.Calls[i].Comps { + comps.AddComp(cmp.Op1, cmp.Op2) if *flagOutput { - fmt.Printf("comp 0x%x:", v) - for arg := range args { - fmt.Printf(" 0x%x", arg) - } - fmt.Printf("\n") + fmt.Printf("comp 0x%x ? 0x%x\n", cmp.Op1, cmp.Op2) } } + ncomps += len(comps) p.MutateWithHints(i, comps, func(p *prog.Prog) bool { ncandidates++ if *flagOutput { @@ -325,8 +322,8 @@ func getKernelUpperBase(target *targets.Target) uint32 { return defaultRet } -func (ctx *Context) dumpCallCoverage(coverFile string, info *ipc.CallInfo) { - if len(info.Cover) == 0 { +func (ctx *Context) dumpCallCoverage(coverFile string, info *flatrpc.CallInfo) { + if info == nil || len(info.Cover) == 0 { return } buf := new(bytes.Buffer) @@ -340,13 +337,13 @@ func (ctx *Context) dumpCallCoverage(coverFile string, info *ipc.CallInfo) { } } -func (ctx *Context) dumpCoverage(coverFile string, info *ipc.ProgInfo) { +func (ctx *Context) dumpCoverage(coverFile string, info *flatrpc.ProgInfo) { for i, inf := range info.Calls { log.Logf(0, "call #%v: signal %v, coverage %v", i, len(inf.Signal), len(inf.Cover)) - ctx.dumpCallCoverage(fmt.Sprintf("%v.%v", coverFile, i), &inf) + ctx.dumpCallCoverage(fmt.Sprintf("%v.%v", coverFile, i), inf) } log.Logf(0, "extra: signal %v, coverage %v", len(info.Extra.Signal), len(info.Extra.Cover)) - ctx.dumpCallCoverage(fmt.Sprintf("%v.extra", coverFile), &info.Extra) + ctx.dumpCallCoverage(fmt.Sprintf("%v.extra", coverFile), info.Extra) } func (ctx *Context) getProgramIndex() int { diff --git a/tools/syz-runtest/runtest.go b/tools/syz-runtest/runtest.go index b1caef092..370bc3954 100644 --- a/tools/syz-runtest/runtest.go +++ b/tools/syz-runtest/runtest.go @@ -1,6 +1,10 @@ // Copyright 2018 syzkaller project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. +// TODO: fold syz-runtest into syz-manager. + +//go:build never + // Runtest runs syzkaller test programs in sys/*/test/*. Start as: // $ syz-runtest -config manager.config // Also see pkg/runtest docs. |
