From 3356f68f1a531e194f6fbca5eb02f4f5bc4c218f Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Tue, 22 Nov 2016 16:59:04 +0100 Subject: vm/qemu: support non-native mode Add config bin_args parameter that contains additional arguments for qemu binary. This allows to specify e.g. "bin_args": "-machine virt -cpu cortex-a57". Also restore qemu debugging output when -debug flag is specified. --- config/config.go | 35 +++++++++++++++++++---------------- vm/qemu/qemu.go | 33 ++++++++++++++++++++++++++++----- vm/vm.go | 1 + 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/config/config.go b/config/config.go index bb8de5b95..9a8562912 100644 --- a/config/config.go +++ b/config/config.go @@ -18,22 +18,23 @@ import ( ) type Config struct { - Name string // Instance name (used for identification and as GCE instance prefix) - Http string // TCP address to serve HTTP stats page (e.g. "localhost:50000") - Rpc string // TCP address to serve RPC for fuzzer processes (optional, only useful for type "none") - Workdir string - Vmlinux string - Kernel string // e.g. arch/x86/boot/bzImage - Tag string // arbitrary optional tag that is saved along with crash reports (e.g. kernel branch/commit) - Cmdline string // kernel command line - Image string // linux image for VMs - Initrd string // linux initial ramdisk. (optional) - Cpu int // number of VM CPUs - Mem int // amount of VM memory in MBs - Sshkey string // root ssh key for the image - Bin string // qemu/lkvm binary name - Debug bool // dump all VM output to console - Output string // one of stdout/dmesg/file (useful only for local VM) + Name string // Instance name (used for identification and as GCE instance prefix) + Http string // TCP address to serve HTTP stats page (e.g. "localhost:50000") + Rpc string // TCP address to serve RPC for fuzzer processes (optional, only useful for type "none") + Workdir string + Vmlinux string + Kernel string // e.g. arch/x86/boot/bzImage + Tag string // arbitrary optional tag that is saved along with crash reports (e.g. kernel branch/commit) + Cmdline string // kernel command line + Image string // linux image for VMs + Initrd string // linux initial ramdisk. (optional) + Cpu int // number of VM CPUs + Mem int // amount of VM memory in MBs + Sshkey string // root ssh key for the image + Bin string // qemu/lkvm binary name + Bin_Args string // additional command line arguments for qemu/lkvm binary + Debug bool // dump all VM output to console + Output string // one of stdout/dmesg/file (useful only for local VM) Hub_Addr string Hub_Key string @@ -258,6 +259,7 @@ func CreateVMConfig(cfg *Config, index int) (*vm.Config, error) { Index: index, Workdir: workdir, Bin: cfg.Bin, + BinArgs: cfg.Bin_Args, Kernel: cfg.Kernel, Cmdline: cfg.Cmdline, Image: cfg.Image, @@ -292,6 +294,7 @@ func checkUnknownFields(data []byte) (string, error) { "Mem", "Sshkey", "Bin", + "Bin_Args", "Debug", "Output", "Hub_Addr", diff --git a/vm/qemu/qemu.go b/vm/qemu/qemu.go index 7856554d7..87a075c00 100644 --- a/vm/qemu/qemu.go +++ b/vm/qemu/qemu.go @@ -16,6 +16,7 @@ import ( "strings" "time" + . "github.com/google/syzkaller/log" "github.com/google/syzkaller/vm" ) @@ -158,11 +159,18 @@ func (inst *instance) Boot() error { "-display", "none", "-serial", "stdio", "-no-reboot", - "-enable-kvm", "-numa", "node,nodeid=0,cpus=0-1", "-numa", "node,nodeid=1,cpus=2-3", "-smp", "sockets=2,cores=2,threads=1", - "-usb", "-usbdevice", "mouse", "-usbdevice", "tablet", - "-soundhw", "all", + } + if inst.cfg.BinArgs == "" { + // This is reasonable defaults for x86 kvm-enabled host. + args = append(args, + "-enable-kvm", + "-usb", "-usbdevice", "mouse", "-usbdevice", "tablet", + "-soundhw", "all", + ) + } else { + args = append(args, strings.Split(inst.cfg.BinArgs, " ")...) } if inst.cfg.Image == "9p" { args = append(args, @@ -194,6 +202,9 @@ func (inst *instance) Boot() error { "-append", cmdline+inst.cfg.Cmdline, ) } + if inst.cfg.Debug { + Logf(0, "running command: %v %#v", inst.cfg.Bin, args) + } qemu := exec.Command(inst.cfg.Bin, args...) qemu.Stdout = inst.wpipe qemu.Stderr = inst.wpipe @@ -281,13 +292,18 @@ func (inst *instance) Copy(hostSrc string) (string, error) { vmDst := filepath.Join(basePath, filepath.Base(hostSrc)) args := append(inst.sshArgs("-P"), hostSrc, "root@localhost:"+vmDst) cmd := exec.Command("scp", args...) + if inst.cfg.Debug { + Logf(0, "running command: scp %#v", args) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stdout + } if err := cmd.Start(); err != nil { return "", err } done := make(chan bool) go func() { select { - case <-time.After(time.Minute): + case <-time.After(3 * time.Minute): cmd.Process.Kill() case <-done: } @@ -308,6 +324,9 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin inst.merger.Add(rpipe) args := append(inst.sshArgs("-p"), "root@localhost", command) + if inst.cfg.Debug { + Logf(0, "running command: ssh %#v", args) + } cmd := exec.Command("ssh", args...) cmd.Stdout = wpipe cmd.Stderr = wpipe @@ -345,7 +364,7 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin } func (inst *instance) sshArgs(portArg string) []string { - return []string{ + args := []string{ "-i", inst.cfg.Sshkey, portArg, strconv.Itoa(inst.port), "-F", "/dev/null", @@ -357,6 +376,10 @@ func (inst *instance) sshArgs(portArg string) []string { "-o", "StrictHostKeyChecking=no", "-o", "LogLevel=error", } + if inst.cfg.Debug { + args = append(args, "-v") + } + return args } const initScript = `#! /bin/bash diff --git a/vm/vm.go b/vm/vm.go index a2ff3c52c..ffd8d1690 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -39,6 +39,7 @@ type Config struct { Index int Workdir string Bin string + BinArgs string Initrd string Kernel string Cmdline string -- cgit mrf-deployment