From b181c36d588da8d6007a23c0ad7305893758cec5 Mon Sep 17 00:00:00 2001 From: Taras Madan Date: Wed, 26 Mar 2025 16:29:08 +0100 Subject: vm: use SSHOptions instead of 4 params It reduces WaitForSSH parameter count from 9 to 6. --- vm/bhyve/bhyve.go | 43 ++++++++++++++++++++-------------------- vm/gce/gce.go | 48 ++++++++++++++++++++++++--------------------- vm/isolated/isolated.go | 52 ++++++++++++++++++++++++------------------------- vm/qemu/qemu.go | 51 ++++++++++++++++++++++++------------------------ vm/vmimpl/util.go | 12 +++++++++--- vm/vmm/vmm.go | 51 ++++++++++++++++++++++++------------------------ 6 files changed, 132 insertions(+), 125 deletions(-) (limited to 'vm') diff --git a/vm/bhyve/bhyve.go b/vm/bhyve/bhyve.go index 35f6354d3..74025e63d 100644 --- a/vm/bhyve/bhyve.go +++ b/vm/bhyve/bhyve.go @@ -42,17 +42,14 @@ type Pool struct { } type instance struct { + vmimpl.SSHOptions 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 @@ -87,12 +84,14 @@ func (pool *Pool) Count() int { func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { inst := &instance{ - cfg: pool.cfg, - debug: pool.env.Debug, - os: pool.env.OS, - sshkey: pool.env.SSHKey, - sshuser: pool.env.SSHUser, - vmName: fmt.Sprintf("syzkaller-%v-%v", pool.env.Name, index), + cfg: pool.cfg, + debug: pool.env.Debug, + os: pool.env.OS, + SSHOptions: vmimpl.SSHOptions{ + Key: pool.env.SSHKey, + User: pool.env.SSHUser, + }, + vmName: fmt.Sprintf("syzkaller-%v-%v", pool.env.Name, index), } dataset := inst.cfg.Dataset @@ -170,11 +169,11 @@ func (inst *instance) Boot() error { netdev := "" if inst.tapdev != "" { - inst.port = 22 + 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) + inst.Port = vmimpl.UnusedTCPPort() + netdev = fmt.Sprintf("slirp,hostfwd=tcp:127.0.0.1:%v-:22", inst.Port) } bhyveArgs := []string{ @@ -251,9 +250,9 @@ func (inst *instance) Boot() error { select { case ip := <-ipch: if inst.tapdev != "" { - inst.sshhost = ip + inst.Addr = ip } else { - inst.sshhost = "localhost" + inst.Addr = "localhost" } case <-inst.merger.Err: bootOutputStop <- true @@ -265,8 +264,8 @@ func (inst *instance) Boot() error { return vmimpl.BootError{Title: "no IP found", Output: bootOutput} } - if err := vmimpl.WaitForSSH(inst.debug, 10*time.Minute, inst.sshhost, - inst.sshkey, inst.sshuser, inst.os, inst.port, nil, false); err != nil { + err = vmimpl.WaitForSSH(10*time.Minute, inst.SSHOptions, inst.os, nil, false, inst.debug) + if err != nil { bootOutputStop <- true <-bootOutputStop return vmimpl.MakeBootError(err, bootOutput) @@ -313,8 +312,8 @@ func (inst *instance) Forward(port int) (string, error) { func (inst *instance) Copy(hostSrc string) (string, error) { vmDst := filepath.Join("/root", filepath.Base(hostSrc)) - args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, inst.port, false), - hostSrc, inst.sshuser+"@"+inst.sshhost+":"+vmDst) + args := append(vmimpl.SCPArgs(inst.debug, inst.Key, inst.Port, false), + hostSrc, inst.User+"@"+inst.Addr+":"+vmDst) if inst.debug { log.Logf(0, "running command: scp %#v", args) } @@ -335,11 +334,11 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin var sshargs []string if inst.forwardPort != 0 { - sshargs = vmimpl.SSHArgsForward(inst.debug, inst.sshkey, inst.port, inst.forwardPort, false) + sshargs = vmimpl.SSHArgsForward(inst.debug, inst.Key, inst.Port, inst.forwardPort, false) } else { - sshargs = vmimpl.SSHArgs(inst.debug, inst.sshkey, inst.port, false) + sshargs = vmimpl.SSHArgs(inst.debug, inst.Key, inst.Port, false) } - args := append(sshargs, inst.sshuser+"@"+inst.sshhost, command) + args := append(sshargs, inst.User+"@"+inst.Addr, command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) } diff --git a/vm/gce/gce.go b/vm/gce/gce.go index 77e9ba113..0da3781ba 100644 --- a/vm/gce/gce.go +++ b/vm/gce/gce.go @@ -70,15 +70,13 @@ type Pool struct { } type instance struct { - env *vmimpl.Env - cfg *Config - GCE *gce.Context - debug bool - name string - ip string + env *vmimpl.Env + cfg *Config + GCE *gce.Context + debug bool + name string + vmimpl.SSHOptions gceKey string // per-instance private ssh key associated with the instance - sshKey string // ssh key - sshUser string closed chan bool consolew io.WriteCloser consoleReadCmd string // optional: command to read non-standard kernel console @@ -217,21 +215,26 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { } log.Logf(0, "wait instance to boot: %v (%v)", name, ip) inst := &instance{ - env: pool.env, - cfg: pool.cfg, - debug: pool.env.Debug, - GCE: pool.GCE, - name: name, - ip: ip, - gceKey: gceKey, - sshKey: sshKey, - sshUser: sshUser, + env: pool.env, + cfg: pool.cfg, + debug: pool.env.Debug, + GCE: pool.GCE, + name: name, + SSHOptions: vmimpl.SSHOptions{ + Addr: ip, + Port: 22, + Key: sshKey, + User: sshUser, + }, + + gceKey: gceKey, + closed: make(chan bool), consoleReadCmd: pool.consoleReadCmd, timeouts: pool.env.Timeouts, } - if err := vmimpl.WaitForSSH(pool.env.Debug, 5*time.Minute, ip, - sshKey, sshUser, pool.env.OS, 22, nil, false); err != nil { + if err := vmimpl.WaitForSSH(5*time.Minute, inst.SSHOptions, + pool.env.OS, nil, false, pool.env.Debug); err != nil { output, outputErr := inst.getSerialPortOutput() if outputErr != nil { output = []byte(fmt.Sprintf("failed to get boot output: %v", outputErr)) @@ -260,7 +263,8 @@ func (inst *instance) Forward(port int) (string, error) { func (inst *instance) Copy(hostSrc string) (string, error) { vmDst := "./" + filepath.Base(hostSrc) - args := append(vmimpl.SCPArgs(true, inst.sshKey, 22, false), hostSrc, inst.sshUser+"@"+inst.ip+":"+vmDst) + args := append(vmimpl.SCPArgs(true, inst.Key, inst.Port, false), + hostSrc, inst.User+"@"+inst.Addr+":"+vmDst) if err := runCmd(inst.debug, "scp", args...); err != nil { return "", err } @@ -416,8 +420,8 @@ func (inst *instance) ssh(args ...string) ([]byte, error) { } func (inst *instance) sshArgs(args ...string) []string { - sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, 22, false), inst.sshUser+"@"+inst.ip) - if inst.env.OS == targets.Linux && inst.sshUser != "root" { + sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.Key, 22, false), inst.User+"@"+inst.Addr) + if inst.env.OS == targets.Linux && inst.User != "root" { args = []string{"sudo", "bash", "-c", "'" + strings.Join(args, " ") + "'"} } return append(sshArgs, args...) diff --git a/vm/isolated/isolated.go b/vm/isolated/isolated.go index 2e5ce50a9..eb70cf369 100755 --- a/vm/isolated/isolated.go +++ b/vm/isolated/isolated.go @@ -46,15 +46,12 @@ type Pool struct { } type instance struct { - cfg *Config + cfg *Config + vmimpl.SSHOptions os string - targetAddr string - targetPort int index int closed chan bool debug bool - sshUser string - sshKey string forwardPort int timeouts targets.Timeouts } @@ -97,16 +94,18 @@ func (pool *Pool) Count() int { func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { targetAddr, targetPort, _ := splitTargetPort(pool.cfg.Targets[index]) inst := &instance{ - cfg: pool.cfg, - os: pool.env.OS, - targetAddr: targetAddr, - targetPort: targetPort, - index: index, - closed: make(chan bool), - debug: pool.env.Debug, - sshUser: pool.env.SSHUser, - sshKey: pool.env.SSHKey, - timeouts: pool.env.Timeouts, + cfg: pool.cfg, + os: pool.env.OS, + SSHOptions: vmimpl.SSHOptions{ + Addr: targetAddr, + Port: targetPort, + User: pool.env.SSHUser, + Key: pool.env.SSHKey, + }, + index: index, + closed: make(chan bool), + debug: pool.env.Debug, + timeouts: pool.env.Timeouts, } closeInst := inst defer func() { @@ -158,8 +157,8 @@ func (inst *instance) ssh(command string) error { } // TODO(dvyukov): who is closing rpipe? - args := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), - inst.sshUser+"@"+inst.targetAddr, command) + args := append(vmimpl.SSHArgs(inst.debug, inst.Key, inst.Port, inst.cfg.SystemSSHCfg), + inst.User+"@"+inst.Addr, command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) } @@ -255,8 +254,7 @@ func (inst *instance) repair() error { } func (inst *instance) waitForSSH(timeout time.Duration) error { - return vmimpl.WaitForSSH(inst.debug, timeout, inst.targetAddr, inst.sshKey, inst.sshUser, - inst.os, inst.targetPort, nil, inst.cfg.SystemSSHCfg) + return vmimpl.WaitForSSH(timeout, inst.SSHOptions, inst.os, nil, inst.cfg.SystemSSHCfg, inst.debug) } func (inst *instance) waitForReboot(timeout int) error { @@ -286,8 +284,8 @@ func (inst *instance) Copy(hostSrc string) (string, error) { baseName := filepath.Base(hostSrc) vmDst := filepath.Join(inst.cfg.TargetDir, baseName) inst.ssh("pkill -9 '" + baseName + "'; rm -f '" + vmDst + "'") - args := append(vmimpl.SCPArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), - hostSrc, inst.sshUser+"@"+inst.targetAddr+":"+vmDst) + args := append(vmimpl.SCPArgs(inst.debug, inst.Key, inst.Port, inst.cfg.SystemSSHCfg), + hostSrc, inst.User+"@"+inst.Addr+":"+vmDst) cmd := osutil.Command("scp", args...) if inst.debug { log.Logf(0, "running command: scp %#v", args) @@ -315,8 +313,8 @@ func (inst *instance) Copy(hostSrc string) (string, error) { func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command string) ( <-chan []byte, <-chan error, error) { - args := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), - inst.sshUser+"@"+inst.targetAddr) + args := append(vmimpl.SSHArgs(inst.debug, inst.Key, inst.Port, inst.cfg.SystemSSHCfg), + inst.User+"@"+inst.Addr) dmesg, err := vmimpl.OpenRemoteConsole("ssh", args...) if err != nil { return nil, nil, err @@ -328,12 +326,12 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin return nil, nil, err } - args = vmimpl.SSHArgsForward(inst.debug, inst.sshKey, inst.targetPort, inst.forwardPort, inst.cfg.SystemSSHCfg) + args = vmimpl.SSHArgsForward(inst.debug, inst.Key, inst.Port, inst.forwardPort, inst.cfg.SystemSSHCfg) if inst.cfg.Pstore { args = append(args, "-o", "ServerAliveInterval=6") args = append(args, "-o", "ServerAliveCountMax=5") } - args = append(args, inst.sshUser+"@"+inst.targetAddr, "cd "+inst.cfg.TargetDir+" && exec "+command) + args = append(args, inst.User+"@"+inst.Addr, "cd "+inst.cfg.TargetDir+" && exec "+command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) } @@ -367,8 +365,8 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin func (inst *instance) readPstoreContents() ([]byte, error) { log.Logf(0, "reading pstore contents") - args := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), - inst.sshUser+"@"+inst.targetAddr, "cat "+pstoreConsoleFile+" && rm "+pstoreConsoleFile) + args := append(vmimpl.SSHArgs(inst.debug, inst.Key, inst.Port, inst.cfg.SystemSSHCfg), + inst.User+"@"+inst.Addr, "cat "+pstoreConsoleFile+" && rm "+pstoreConsoleFile) if inst.debug { log.Logf(0, "running command: ssh %#v", args) } diff --git a/vm/qemu/qemu.go b/vm/qemu/qemu.go index 2b477ffbb..ca7e9a48b 100644 --- a/vm/qemu/qemu.go +++ b/vm/qemu/qemu.go @@ -87,20 +87,18 @@ type Pool struct { } type instance struct { - index int - cfg *Config - target *targets.Target - archConfig *archConfig - version string - args []string - image string - debug bool - os string - workdir string - sshkey string - sshuser string + index int + cfg *Config + target *targets.Target + archConfig *archConfig + version string + args []string + image string + debug bool + os string + workdir string + vmimpl.SSHOptions timeouts targets.Timeouts - port int monport int forwardPort int mon net.Conn @@ -372,8 +370,12 @@ func (pool *Pool) ctor(workdir, sshkey, sshuser string, index int) (*instance, e os: pool.env.OS, timeouts: pool.env.Timeouts, workdir: workdir, - sshkey: sshkey, - sshuser: sshuser, + SSHOptions: vmimpl.SSHOptions{ + Addr: "localhost", + Port: vmimpl.UnusedTCPPort(), + Key: sshkey, + User: sshuser, + }, } if pool.env.Snapshot { inst.snapshot = new(snapshot) @@ -429,7 +431,6 @@ func (inst *instance) Close() error { } func (inst *instance) boot() error { - inst.port = vmimpl.UnusedTCPPort() inst.monport = vmimpl.UnusedTCPPort() args, err := inst.buildQemuArgs() if err != nil { @@ -479,8 +480,8 @@ func (inst *instance) boot() error { } } - if err := vmimpl.WaitForSSH(inst.debug, 10*time.Minute*inst.timeouts.Scale, "localhost", - inst.sshkey, inst.sshuser, inst.os, inst.port, inst.merger.Err, false); err != nil { + if err := vmimpl.WaitForSSH(10*time.Minute*inst.timeouts.Scale, inst.SSHOptions, + inst.os, inst.merger.Err, false, inst.debug); err != nil { bootOutputStop <- true <-bootOutputStop return vmimpl.MakeBootError(err, bootOutput) @@ -507,7 +508,7 @@ func (inst *instance) buildQemuArgs() ([]string, error) { args = append(args, splitArgs(inst.cfg.QemuArgs, templateDir, inst.index)...) args = append(args, "-device", inst.cfg.NetDev+",netdev=net0", - "-netdev", fmt.Sprintf("user,id=net0,restrict=on,hostfwd=tcp:127.0.0.1:%v-:22", inst.port), + "-netdev", fmt.Sprintf("user,id=net0,restrict=on,hostfwd=tcp:127.0.0.1:%v-:22", inst.Port), ) if inst.image == "9p" { args = append(args, @@ -654,8 +655,8 @@ func (inst *instance) Copy(hostSrc string) (string, error) { inst.files[vmDst] = hostSrc } - args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, inst.port, false), - hostSrc, inst.sshuser+"@localhost:"+vmDst) + args := append(vmimpl.SCPArgs(inst.debug, inst.Key, inst.Port, false), + hostSrc, inst.User+"@localhost:"+vmDst) if inst.debug { log.Logf(0, "running command: scp %#v", args) } @@ -674,7 +675,7 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin } inst.merger.Add("ssh", rpipe) - sshArgs := vmimpl.SSHArgsForward(inst.debug, inst.sshkey, inst.port, inst.forwardPort, false) + sshArgs := vmimpl.SSHArgsForward(inst.debug, inst.User, inst.Port, inst.forwardPort, false) args := strings.Split(command, " ") if bin := filepath.Base(args[0]); inst.target.HostFuzzer && bin == "syz-execprog" { // Weird mode for Fuchsia. @@ -683,7 +684,7 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin for i, arg := range args { if strings.HasPrefix(arg, "-executor=") { args[i] = "-executor=" + "/usr/bin/ssh " + strings.Join(sshArgs, " ") + - " " + inst.sshuser + "@localhost " + arg[len("-executor="):] + " " + inst.User + "@localhost " + arg[len("-executor="):] } if host := inst.files[arg]; host != "" { args[i] = host @@ -692,7 +693,7 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin } else { args = []string{"ssh"} args = append(args, sshArgs...) - args = append(args, inst.sshuser+"@localhost", "cd "+inst.targetDir()+" && "+command) + args = append(args, inst.User+"@localhost", "cd "+inst.targetDir()+" && "+command) } if inst.debug { log.Logf(0, "running command: %#v", args) @@ -745,7 +746,7 @@ func (inst *instance) ssh(args ...string) ([]byte, error) { } func (inst *instance) sshArgs(args ...string) []string { - sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshkey, inst.port, false), inst.sshuser+"@localhost") + sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.User, inst.Port, false), inst.User+"@localhost") return append(sshArgs, args...) } diff --git a/vm/vmimpl/util.go b/vm/vmimpl/util.go index a04914e6d..2df514ac6 100644 --- a/vm/vmimpl/util.go +++ b/vm/vmimpl/util.go @@ -23,8 +23,14 @@ func SleepInterruptible(d time.Duration) bool { } } -func WaitForSSH(debug bool, timeout time.Duration, addr, sshKey, sshUser, OS string, port int, stop chan error, - systemSSHCfg bool) error { +type SSHOptions struct { + Addr string + Port int + User string + Key string +} + +func WaitForSSH(timeout time.Duration, opts SSHOptions, OS string, stop chan error, systemSSHCfg, debug bool) error { pwd := "pwd" if OS == targets.Windows { pwd = "dir" @@ -39,7 +45,7 @@ func WaitForSSH(debug bool, timeout time.Duration, addr, sshKey, sshUser, OS str case <-Shutdown: return fmt.Errorf("shutdown in progress") } - args := append(SSHArgs(debug, sshKey, port, systemSSHCfg), sshUser+"@"+addr, pwd) + args := append(SSHArgs(debug, opts.Key, opts.Port, systemSSHCfg), opts.User+"@"+opts.Addr, pwd) if debug { log.Logf(0, "running ssh: %#v", args) } diff --git a/vm/vmm/vmm.go b/vm/vmm/vmm.go index 90ec66ad7..35fdf7650 100644 --- a/vm/vmm/vmm.go +++ b/vm/vmm/vmm.go @@ -44,14 +44,11 @@ type Pool struct { } type instance struct { - cfg *Config - image string - debug bool - os string - sshkey string - sshuser string - sshhost string - sshport int + cfg *Config + image string + debug bool + os string + vmimpl.SSHOptions merger *vmimpl.OutputMerger vmName string vmm *exec.Cmd @@ -101,15 +98,17 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { tee = os.Stdout } inst := &instance{ - cfg: pool.cfg, - image: filepath.Join(workdir, "disk.qcow2"), - debug: pool.env.Debug, - os: pool.env.OS, - sshkey: pool.env.SSHKey, - sshuser: pool.env.SSHUser, - sshport: 22, - vmName: fmt.Sprintf("%v-%v", pool.env.Name, index), - merger: vmimpl.NewOutputMerger(tee), + cfg: pool.cfg, + image: filepath.Join(workdir, "disk.qcow2"), + debug: pool.env.Debug, + os: pool.env.OS, + SSHOptions: vmimpl.SSHOptions{ + Key: pool.env.SSHKey, + User: pool.env.SSHUser, + Port: 22, + }, + vmName: fmt.Sprintf("%v-%v", pool.env.Name, index), + merger: vmimpl.NewOutputMerger(tee), } // Stop the instance from the previous run in case it's still running. @@ -180,13 +179,13 @@ func (inst *instance) Boot() error { inr.Close() inst.merger.Add("console", outr) - inst.sshhost, err = inst.lookupSSHAddress() + inst.Addr, err = inst.lookupSSHAddress() if err != nil { return err } - if err := vmimpl.WaitForSSH(inst.debug, 20*time.Minute, inst.sshhost, - inst.sshkey, inst.sshuser, inst.os, inst.sshport, nil, false); err != nil { + if err := vmimpl.WaitForSSH(20*time.Minute, inst.SSHOptions, + inst.os, nil, false, inst.debug); err != nil { out := <-inst.merger.Output return vmimpl.BootError{Title: err.Error(), Output: out} } @@ -229,9 +228,9 @@ func (inst *instance) Close() error { } func (inst *instance) Forward(port int) (string, error) { - octets := strings.Split(inst.sshhost, ".") + octets := strings.Split(inst.Addr, ".") if len(octets) < 3 { - return "", fmt.Errorf("too few octets in hostname %v", inst.sshhost) + return "", fmt.Errorf("too few octets in hostname %v", inst.Addr) } addr := fmt.Sprintf("%v.%v.%v.2:%v", octets[0], octets[1], octets[2], port) return addr, nil @@ -239,8 +238,8 @@ func (inst *instance) Forward(port int) (string, error) { func (inst *instance) Copy(hostSrc string) (string, error) { vmDst := filepath.Join("/root", filepath.Base(hostSrc)) - args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, inst.sshport, false), - hostSrc, inst.sshuser+"@"+inst.sshhost+":"+vmDst) + args := append(vmimpl.SCPArgs(inst.debug, inst.Key, inst.Port, false), + hostSrc, inst.User+"@"+inst.Addr+":"+vmDst) if inst.debug { log.Logf(0, "running command: scp %#v", args) } @@ -259,8 +258,8 @@ 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, inst.sshport, false), - inst.sshuser+"@"+inst.sshhost, command) + args := append(vmimpl.SSHArgs(inst.debug, inst.Key, inst.Port, false), + inst.User+"@"+inst.Addr, command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) } -- cgit mrf-deployment