From 8d5ba3821f70c961f6b42e64dbd6aaaace399b5e Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 18 Dec 2017 15:51:00 +0100 Subject: syz-fuzzer: move program logging into a separate function --- syz-fuzzer/fuzzer.go | 25 +++++++++++++++-- syz-fuzzer/proc.go | 79 ++++++++++++++++++++++++++++------------------------ 2 files changed, 66 insertions(+), 38 deletions(-) diff --git a/syz-fuzzer/fuzzer.go b/syz-fuzzer/fuzzer.go index 2b9c9514d..31522e97f 100644 --- a/syz-fuzzer/fuzzer.go +++ b/syz-fuzzer/fuzzer.go @@ -51,6 +51,8 @@ var ( ) type Fuzzer struct { + name string + outputType OutputType config *ipc.Config execOpts *ipc.ExecOpts procs []*Proc @@ -83,11 +85,28 @@ const ( StatCount ) +type OutputType int + +const ( + OutputNone OutputType = iota + OutputStdout + OutputDmesg + OutputFile +) + func main() { debug.SetGCPercent(50) flag.Parse() + var outputType OutputType switch *flagOutput { - case "none", "stdout", "dmesg", "file": + case "none": + outputType = OutputNone + case "stdout": + outputType = OutputStdout + case "dmesg": + outputType = OutputDmesg + case "file": + outputType = OutputFile default: fmt.Fprintf(os.Stderr, "-output flag must be one of none/stdout/dmesg/file\n") os.Exit(1) @@ -211,6 +230,8 @@ func main() { needPoll := make(chan struct{}, 1) needPoll <- struct{}{} fuzzer := &Fuzzer{ + name: *flagName, + outputType: outputType, config: config, execOpts: execOpts, gate: ipc.NewGate(2**flagProcs, leakCallback), @@ -274,7 +295,7 @@ func main() { } a := &PollArgs{ - Name: *flagName, + Name: fuzzer.name, NeedCandidates: needCandidates, Stats: make(map[string]uint64), } diff --git a/syz-fuzzer/proc.go b/syz-fuzzer/proc.go index 5491a31b1..0faa7189d 100644 --- a/syz-fuzzer/proc.go +++ b/syz-fuzzer/proc.go @@ -159,7 +159,7 @@ func (proc *Proc) triageInput(item *WorkTriage) { Logf(2, "added new input for %v to corpus:\n%s", call.CallName, data) a := &NewInputArgs{ - Name: *flagName, + Name: proc.fuzzer.name, RpcInput: RpcInput{ Call: call.CallName, Prog: data, @@ -257,7 +257,6 @@ func (proc *Proc) execute(execOpts *ipc.ExecOpts, p *prog.Prog, var logMu sync.Mutex func (proc *Proc) executeRaw(opts *ipc.ExecOpts, p *prog.Prog, stat Stat) []ipc.CallInfo { - pid := proc.pid if opts.Flags&ipc.FlagDedupCover == 0 { panic("dedup cover is not enabled") } @@ -266,40 +265,7 @@ func (proc *Proc) executeRaw(opts *ipc.ExecOpts, p *prog.Prog, stat Stat) []ipc. ticket := proc.fuzzer.gate.Enter() defer proc.fuzzer.gate.Leave(ticket) - strOpts := "" - if opts.Flags&ipc.FlagInjectFault != 0 { - strOpts = fmt.Sprintf(" (fault-call:%v fault-nth:%v)", opts.FaultCall, opts.FaultNth) - } - - // The following output helps to understand what program crashed kernel. - // It must not be intermixed. - switch *flagOutput { - case "none": - // This case intentionally left blank. - case "stdout": - data := p.Serialize() - logMu.Lock() - Logf(0, "executing program %v%v:\n%s", pid, strOpts, data) - logMu.Unlock() - case "dmesg": - fd, err := syscall.Open("/dev/kmsg", syscall.O_WRONLY, 0) - if err == nil { - buf := new(bytes.Buffer) - fmt.Fprintf(buf, "syzkaller: executing program %v%v:\n%s", pid, strOpts, p.Serialize()) - syscall.Write(fd, buf.Bytes()) - syscall.Close(fd) - } - case "file": - f, err := os.Create(fmt.Sprintf("%v-%v.prog", *flagName, pid)) - if err == nil { - if strOpts != "" { - fmt.Fprintf(f, "#%v\n", strOpts) - } - f.Write(p.Serialize()) - f.Close() - } - } - + proc.logProgram(opts, p) try := 0 retry: atomic.AddUint64(&proc.fuzzer.stats[stat], 1) @@ -323,3 +289,44 @@ retry: Logf(2, "result failed=%v hanged=%v: %v\n", failed, hanged, string(output)) return info } + +func (proc *Proc) logProgram(opts *ipc.ExecOpts, p *prog.Prog) { + if proc.fuzzer.outputType == OutputNone { + return + } + + data := p.Serialize() + strOpts := "" + if opts.Flags&ipc.FlagInjectFault != 0 { + strOpts = fmt.Sprintf(" (fault-call:%v fault-nth:%v)", opts.FaultCall, opts.FaultNth) + } + + // The following output helps to understand what program crashed kernel. + // It must not be intermixed. + switch proc.fuzzer.outputType { + case OutputStdout: + logMu.Lock() + Logf(0, "executing program %v%v:\n%s", proc.pid, strOpts, data) + logMu.Unlock() + case OutputDmesg: + fd, err := syscall.Open("/dev/kmsg", syscall.O_WRONLY, 0) + if err == nil { + buf := new(bytes.Buffer) + fmt.Fprintf(buf, "syzkaller: executing program %v%v:\n%s", + proc.pid, strOpts, data) + syscall.Write(fd, buf.Bytes()) + syscall.Close(fd) + } + case OutputFile: + f, err := os.Create(fmt.Sprintf("%v-%v.prog", proc.fuzzer.name, proc.pid)) + if err == nil { + if strOpts != "" { + fmt.Fprintf(f, "#%v\n", strOpts) + } + f.Write(data) + f.Close() + } + default: + panic("unknown output type") + } +} -- cgit mrf-deployment