aboutsummaryrefslogtreecommitdiffstats
path: root/vm
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2024-05-26 17:13:38 -0400
committerDmitry Vyukov <dvyukov@google.com>2024-05-27 17:01:28 +0000
commitf486078ac5d3eca51b34d2fdedeeba2a729f6296 (patch)
tree6223ccdc54da8169ab39daec64679e54e00a3fc3 /vm
parent0cdd36fc443630fa8b6c5d7903cb7adc0baac5b5 (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.go93
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)
}