From 4a623fface69b3124c66c6b0859ab1fc08b47e47 Mon Sep 17 00:00:00 2001 From: Aleksandr Nogikh Date: Mon, 13 May 2024 16:30:18 +0200 Subject: syz-manager: fix a race in logProgram() logProgram() may race with Request.Done(), in which case the request producer (fuzzer.Fuzzer) may well have already mutated a previously executed prog.Prog instance. --- syz-manager/rpc.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/syz-manager/rpc.go b/syz-manager/rpc.go index 7323d5e38..ef4b81361 100644 --- a/syz-manager/rpc.go +++ b/syz-manager/rpc.go @@ -86,9 +86,10 @@ type Runner struct { } type Request struct { - req *fuzzer.Request - try int - procID int + req *fuzzer.Request + serialized []byte + try int + procID int } type BugFrames struct { @@ -316,7 +317,7 @@ func (serv *RPCServer) StartExecuting(a *rpctype.ExecutingRequest, r *int) error } runner.requests[a.ID] = req runner.mu.Unlock() - runner.logProgram(a.ProcID, req.req.Prog) + runner.logProgram(a.ProcID, req.serialized) return nil } @@ -529,7 +530,7 @@ func (serv *RPCServer) doneRequest(runner *Runner, resp rpctype.ExecutionResult, // RPC handlers are invoked in separate goroutines, so log the program here // if completion notification outrun start executing notification. if req.try < resp.Try { - runner.logProgram(resp.ProcID, req.req.Prog) + runner.logProgram(resp.ProcID, req.serialized) } if !serv.cfg.Cover { addFallbackSignal(req.req.Prog, info) @@ -550,6 +551,9 @@ func (serv *RPCServer) newRequest(runner *Runner, req *fuzzer.Request) (rpctype. return rpctype.ExecutionRequest{}, false } + // logProgram() may race with Done(), so let's serialize the program right now. + serialized := req.Prog.Serialize() + var signalFilter signal.Signal if req.SignalFilter != nil { newRawSignal := runner.instModules.Decanonicalize(req.SignalFilter.ToRaw()) @@ -561,8 +565,9 @@ func (serv *RPCServer) newRequest(runner *Runner, req *fuzzer.Request) (rpctype. id := runner.nextRequestID if runner.requests != nil { runner.requests[id] = Request{ - req: req, - try: -1, + req: req, + try: -1, + serialized: serialized, } } runner.mu.Unlock() @@ -616,9 +621,9 @@ func (serv *RPCServer) createExecOpts(req *fuzzer.Request) ipc.ExecOpts { } } -func (runner *Runner) logProgram(procID int, p *prog.Prog) { +func (runner *Runner) logProgram(procID int, serialized []byte) { buf := new(bytes.Buffer) - fmt.Fprintf(buf, "executing program %v:\n%s\n", procID, p.Serialize()) + fmt.Fprintf(buf, "executing program %v:\n%s\n", procID, serialized) select { case runner.injectLog <- buf.Bytes(): case <-runner.injectStop: -- cgit mrf-deployment