aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--syz-manager/manager.go26
-rw-r--r--vm/qemu/qemu.go20
-rw-r--r--vm/vm.go7
-rw-r--r--vm/vmimpl/vmimpl.go6
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 {
diff --git a/vm/vm.go b/vm/vm.go
index 0c40ba2f3..d5a1f35db 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -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