diff options
| author | Mark Johnston <markj@FreeBSD.org> | 2024-05-26 17:13:38 -0400 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-05-27 17:01:28 +0000 |
| commit | f486078ac5d3eca51b34d2fdedeeba2a729f6296 (patch) | |
| tree | 6223ccdc54da8169ab39daec64679e54e00a3fc3 /vm | |
| parent | 0cdd36fc443630fa8b6c5d7903cb7adc0baac5b5 (diff) | |
vm/bhyve: add support for the slirp network backend
bhyve recently grew support for using libslirp (from QEMU) as the
networking backend, which is useful for syzkaller since it requires no
configuration on the host. This patch causes syz-manager to make use of
the slirp backend when no VM bridge is configured.
Diffstat (limited to 'vm')
| -rw-r--r-- | vm/bhyve/bhyve.go | 93 |
1 files changed, 63 insertions, 30 deletions
diff --git a/vm/bhyve/bhyve.go b/vm/bhyve/bhyve.go index c3b53e053..1570b7939 100644 --- a/vm/bhyve/bhyve.go +++ b/vm/bhyve/bhyve.go @@ -25,7 +25,7 @@ func init() { } type Config struct { - Bridge string `json:"bridge"` // name of network bridge device + Bridge string `json:"bridge"` // name of network bridge device, optional Count int `json:"count"` // number of VMs to use CPU int `json:"cpu"` // number of VM vCPU HostIP string `json:"hostip"` // VM host IP address @@ -39,19 +39,21 @@ type Pool struct { } type instance struct { - cfg *Config - snapshot string - tapdev string - image string - debug bool - os string - sshkey string - sshuser string - sshhost string - merger *vmimpl.OutputMerger - vmName string - bhyve *exec.Cmd - consolew io.WriteCloser + cfg *Config + snapshot string + tapdev string + port int + forwardPort int + image string + debug bool + os string + sshkey string + sshuser string + sshhost string + merger *vmimpl.OutputMerger + vmName string + bhyve *exec.Cmd + consolew io.WriteCloser } var ipRegex = regexp.MustCompile(`bound to (([0-9]+\.){3}[0-9]+) `) @@ -129,15 +131,17 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { return nil, err } - tapdev, err := osutil.RunCmd(time.Minute, "", "ifconfig", "tap", "create") - if err != nil { - inst.Close() - return nil, err - } - inst.tapdev = tapRegex.FindString(string(tapdev)) - if _, err := osutil.RunCmd(time.Minute, "", "ifconfig", inst.cfg.Bridge, "addm", inst.tapdev); err != nil { - inst.Close() - return nil, err + if inst.cfg.Bridge != "" { + tapdev, err := osutil.RunCmd(time.Minute, "", "ifconfig", "tap", "create") + if err != nil { + inst.Close() + return nil, err + } + inst.tapdev = tapRegex.FindString(string(tapdev)) + if _, err := osutil.RunCmd(time.Minute, "", "ifconfig", inst.cfg.Bridge, "addm", inst.tapdev); err != nil { + inst.Close() + return nil, err + } } if err := inst.Boot(); err != nil { @@ -165,13 +169,22 @@ func (inst *instance) Boot() error { return err } + netdev := "" + if inst.tapdev != "" { + inst.port = 22 + netdev = inst.tapdev + } else { + inst.port = vmimpl.UnusedTCPPort() + netdev = fmt.Sprintf("slirp,hostfwd=tcp:127.0.0.1:%v-:22", inst.port) + } + bhyveArgs := []string{ "-H", "-A", "-P", "-c", fmt.Sprintf("%d", inst.cfg.CPU), "-m", inst.cfg.Mem, "-s", "0:0,hostbridge", "-s", "1:0,lpc", - "-s", fmt.Sprintf("2:0,virtio-net,%v", inst.tapdev), + "-s", fmt.Sprintf("2:0,virtio-net,%v", netdev), "-s", fmt.Sprintf("3:0,virtio-blk,%v", inst.image), "-l", "com1,stdio", inst.vmName, @@ -238,7 +251,11 @@ func (inst *instance) Boot() error { select { case ip := <-ipch: - inst.sshhost = ip + if inst.tapdev != "" { + inst.sshhost = ip + } else { + inst.sshhost = "localhost" + } case <-inst.merger.Err: bootOutputStop <- true <-bootOutputStop @@ -250,7 +267,7 @@ func (inst *instance) Boot() error { } if err := vmimpl.WaitForSSH(inst.debug, 10*time.Minute, inst.sshhost, - inst.sshkey, inst.sshuser, inst.os, 22, nil, false); err != nil { + inst.sshkey, inst.sshuser, inst.os, inst.port, nil, false); err != nil { bootOutputStop <- true <-bootOutputStop return vmimpl.MakeBootError(err, bootOutput) @@ -280,12 +297,23 @@ func (inst *instance) Close() { } func (inst *instance) Forward(port int) (string, error) { - return fmt.Sprintf("%v:%v", inst.cfg.HostIP, port), nil + if inst.tapdev != "" { + return fmt.Sprintf("%v:%v", inst.cfg.HostIP, port), nil + } else { + if port == 0 { + return "", fmt.Errorf("vm/bhyve: forward port is zero") + } + if inst.forwardPort != 0 { + return "", fmt.Errorf("vm/bhyve: forward port is already set") + } + inst.forwardPort = port + return fmt.Sprintf("localhost:%v", port), nil + } } func (inst *instance) Copy(hostSrc string) (string, error) { vmDst := filepath.Join("/root", filepath.Base(hostSrc)) - args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, 22, false), + args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, inst.port, false), hostSrc, inst.sshuser+"@"+inst.sshhost+":"+vmDst) if inst.debug { log.Logf(0, "running command: scp %#v", args) @@ -305,8 +333,13 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin } inst.merger.Add("ssh", rpipe) - args := append(vmimpl.SSHArgs(inst.debug, inst.sshkey, 22, false), - inst.sshuser+"@"+inst.sshhost, command) + sshargs := []string{} + if inst.forwardPort != 0 { + sshargs = vmimpl.SSHArgsForward(inst.debug, inst.sshkey, inst.port, inst.forwardPort, false) + } else { + sshargs = vmimpl.SSHArgs(inst.debug, inst.sshkey, inst.port, false) + } + args := append(sshargs, inst.sshuser+"@"+inst.sshhost, command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) } |
