diff options
| -rw-r--r-- | syz-manager/manager.go | 26 | ||||
| -rw-r--r-- | vm/qemu/qemu.go | 20 | ||||
| -rw-r--r-- | vm/vm.go | 7 | ||||
| -rw-r--r-- | vm/vmimpl/vmimpl.go | 6 |
4 files changed, 51 insertions, 8 deletions
diff --git a/syz-manager/manager.go b/syz-manager/manager.go index 517ed0052..0c3ceecec 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -557,9 +557,12 @@ func (mgr *Manager) runInstance(index int) (*Crash, error) { mgr.checkUsedFiles() instanceName := fmt.Sprintf("vm-%d", index) - rep, err := mgr.runInstanceInner(index, instanceName) + rep, vmInfo, err := mgr.runInstanceInner(index, instanceName) machineInfo := mgr.serv.shutdownInstance(instanceName) + if len(vmInfo) != 0 { + machineInfo = append(append(vmInfo, '\n'), machineInfo...) + } // Error that is not a VM crash. if err != nil { @@ -578,21 +581,21 @@ func (mgr *Manager) runInstance(index int) (*Crash, error) { return crash, nil } -func (mgr *Manager) runInstanceInner(index int, instanceName string) (*report.Report, error) { +func (mgr *Manager) runInstanceInner(index int, instanceName string) (*report.Report, []byte, error) { inst, err := mgr.vmPool.Create(index) if err != nil { - return nil, fmt.Errorf("failed to create instance: %v", err) + return nil, nil, fmt.Errorf("failed to create instance: %v", err) } defer inst.Close() fwdAddr, err := inst.Forward(mgr.serv.port) if err != nil { - return nil, fmt.Errorf("failed to setup port forwarding: %v", err) + return nil, nil, fmt.Errorf("failed to setup port forwarding: %v", err) } fuzzerBin, err := inst.Copy(mgr.cfg.FuzzerBin) if err != nil { - return nil, fmt.Errorf("failed to copy binary: %v", err) + return nil, nil, fmt.Errorf("failed to copy binary: %v", err) } // If ExecutorBin is provided, it means that syz-executor is already in the image, @@ -601,7 +604,7 @@ func (mgr *Manager) runInstanceInner(index int, instanceName string) (*report.Re if executorBin == "" { executorBin, err = inst.Copy(mgr.cfg.ExecutorBin) if err != nil { - return nil, fmt.Errorf("failed to copy binary: %v", err) + return nil, nil, fmt.Errorf("failed to copy binary: %v", err) } } @@ -622,15 +625,22 @@ func (mgr *Manager) runInstanceInner(index int, instanceName string) (*report.Re mgr.cfg.Cover, *flagDebug, false, false, true, mgr.cfg.Timeouts.Slowdown) outc, errc, err := inst.Run(mgr.cfg.Timeouts.VMRunningTime, mgr.vmStop, cmd) if err != nil { - return nil, fmt.Errorf("failed to run fuzzer: %v", err) + return nil, nil, fmt.Errorf("failed to run fuzzer: %v", err) } + var vmInfo []byte rep := inst.MonitorExecution(outc, errc, mgr.reporter, vm.ExitTimeout) if rep == nil { // This is the only "OK" outcome. log.Logf(0, "%s: running for %v, restarting", instanceName, time.Since(start)) + } else { + vmInfo, err = inst.Info() + if err != nil { + vmInfo = []byte(fmt.Sprintf("error getting VM info: %v\n", err)) + } } - return rep, nil + + return rep, vmInfo, nil } func (mgr *Manager) emailCrash(crash *Crash) { diff --git a/vm/qemu/qemu.go b/vm/qemu/qemu.go index 5ada86950..653e9e692 100644 --- a/vm/qemu/qemu.go +++ b/vm/qemu/qemu.go @@ -4,6 +4,7 @@ package qemu import ( + "bytes" "encoding/json" "fmt" "io" @@ -24,6 +25,7 @@ import ( ) func init() { + var _ vmimpl.Infoer = (*instance)(nil) vmimpl.Register("qemu", ctor, true) } @@ -71,6 +73,7 @@ type Pool struct { cfg *Config target *targets.Target archConfig *archConfig + version string } type instance struct { @@ -78,6 +81,8 @@ type instance struct { cfg *Config target *targets.Target archConfig *archConfig + version string + args []string image string debug bool os string @@ -291,9 +296,17 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) { } cfg.Kernel = osutil.Abs(cfg.Kernel) cfg.Initrd = osutil.Abs(cfg.Initrd) + + output, err := osutil.RunCmd(time.Minute, "", cfg.Qemu, "--version") + if err != nil { + return nil, err + } + version := string(bytes.Split(output, []byte{'\n'})[0]) + pool := &Pool{ env: env, cfg: cfg, + version: version, target: targets.Get(env.OS, env.Arch), archConfig: archConfig, } @@ -339,6 +352,7 @@ func (pool *Pool) ctor(workdir, sshkey, sshuser string, index int) (vmimpl.Insta cfg: pool.cfg, target: pool.target, archConfig: pool.archConfig, + version: pool.version, image: pool.env.Image, debug: pool.env.Debug, os: pool.env.OS, @@ -465,6 +479,7 @@ func (inst *instance) boot() error { if inst.debug { log.Logf(0, "running command: %v %#v", inst.cfg.Qemu, args) } + inst.args = args qemu := osutil.Command(inst.cfg.Qemu, args...) qemu.Stdout = inst.wpipe qemu.Stderr = inst.wpipe @@ -647,6 +662,11 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin return inst.merger.Output, errc, nil } +func (inst *instance) Info() ([]byte, error) { + info := fmt.Sprintf("%v\n%v %q\n", inst.version, inst.cfg.Qemu, inst.args) + return []byte(info), nil +} + func (inst *instance) Diagnose(rep *report.Report) ([]byte, bool) { if inst.target.OS == targets.Linux { if output, wait, handled := vmimpl.DiagnoseLinux(rep, inst.ssh); handled { @@ -143,6 +143,13 @@ func (inst *Instance) Run(timeout time.Duration, stop <-chan bool, command strin return inst.impl.Run(timeout, stop, command) } +func (inst *Instance) Info() ([]byte, error) { + if ii, ok := inst.impl.(vmimpl.Infoer); ok { + return ii.Info() + } + return nil, nil +} + func (inst *Instance) diagnose(rep *report.Report) ([]byte, bool) { if rep == nil { panic("rep is nil") diff --git a/vm/vmimpl/vmimpl.go b/vm/vmimpl/vmimpl.go index 5a8fed098..b3b7b19e4 100644 --- a/vm/vmimpl/vmimpl.go +++ b/vm/vmimpl/vmimpl.go @@ -59,6 +59,12 @@ type Instance interface { Close() } +// Infoer is an optional interface that can be implemented by Instance. +type Infoer interface { + // MachineInfo returns additional info about the VM, e.g. VMM version/arguments. + Info() ([]byte, error) +} + // Env contains global constant parameters for a pool of VMs. type Env struct { // Unique name |
