From 41ee133f71cd3d24faeac9b158c749637acb8e8d Mon Sep 17 00:00:00 2001 From: Florent Revest Date: Mon, 18 Mar 2024 19:25:04 +0100 Subject: vm/isolated: allow the use of system-wide SSH config Most of the VM types tightly manage the target they SSH into and can safely assume that system wide SSH configuration would mess with the SSH flags provided by syzkaller. However, in the "isolate" VM type, one can connect to a host that is not at all managed by syzkaller. In this case, it can be useful to leverage system wide SSH config, maybe provided by a corporate environment. This adds an option to the isolated config to skip some of the SSH and SCP flags that would drop system wide config. --- vm/bhyve/bhyve.go | 6 +++--- vm/cuttlefish/cuttlefish.go | 2 +- vm/gce/gce.go | 8 ++++---- vm/isolated/isolated.go | 14 ++++++++------ vm/qemu/qemu.go | 8 ++++---- vm/vmimpl/util.go | 34 +++++++++++++++++++--------------- vm/vmm/vmm.go | 6 +++--- vm/vmware/vmware.go | 4 ++-- 8 files changed, 44 insertions(+), 38 deletions(-) (limited to 'vm') diff --git a/vm/bhyve/bhyve.go b/vm/bhyve/bhyve.go index cb942f8d6..c3b53e053 100644 --- a/vm/bhyve/bhyve.go +++ b/vm/bhyve/bhyve.go @@ -250,7 +250,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); err != nil { + inst.sshkey, inst.sshuser, inst.os, 22, nil, false); err != nil { bootOutputStop <- true <-bootOutputStop return vmimpl.MakeBootError(err, bootOutput) @@ -285,7 +285,7 @@ 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, 22), + args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, 22, false), hostSrc, inst.sshuser+"@"+inst.sshhost+":"+vmDst) if inst.debug { log.Logf(0, "running command: scp %#v", args) @@ -305,7 +305,7 @@ 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), + args := append(vmimpl.SSHArgs(inst.debug, inst.sshkey, 22, false), inst.sshuser+"@"+inst.sshhost, command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) diff --git a/vm/cuttlefish/cuttlefish.go b/vm/cuttlefish/cuttlefish.go index 48cbcbbe0..94610ed4e 100644 --- a/vm/cuttlefish/cuttlefish.go +++ b/vm/cuttlefish/cuttlefish.go @@ -104,7 +104,7 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { } func (inst *instance) sshArgs(command string) []string { - sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, 22), inst.sshUser+"@"+inst.name) + sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, 22, false), inst.sshUser+"@"+inst.name) if inst.sshUser != "root" { return append(sshArgs, "sudo", "bash", "-c", "'"+command+"'") } diff --git a/vm/gce/gce.go b/vm/gce/gce.go index f775f43b5..16f3f996f 100644 --- a/vm/gce/gce.go +++ b/vm/gce/gce.go @@ -228,7 +228,7 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { consoleReadCmd: pool.consoleReadCmd, } if err := vmimpl.WaitForSSH(pool.env.Debug, 5*time.Minute, ip, - sshKey, sshUser, pool.env.OS, 22, nil); err != nil { + sshKey, sshUser, pool.env.OS, 22, nil, false); err != nil { output, outputErr := inst.getSerialPortOutput() if outputErr != nil { output = []byte(fmt.Sprintf("failed to get boot output: %v", outputErr)) @@ -253,7 +253,7 @@ 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), hostSrc, inst.sshUser+"@"+inst.ip+":"+vmDst) + args := append(vmimpl.SCPArgs(true, inst.sshKey, 22, false), hostSrc, inst.sshUser+"@"+inst.ip+":"+vmDst) if err := runCmd(inst.debug, "scp", args...); err != nil { return "", err } @@ -433,7 +433,7 @@ func (inst *instance) ssh(args ...string) ([]byte, error) { } func (inst *instance) sshArgs(args ...string) []string { - sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, 22), inst.sshUser+"@"+inst.ip) + sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, 22, false), inst.sshUser+"@"+inst.ip) if inst.env.OS == targets.Linux && inst.sshUser != "root" { args = []string{"sudo", "bash", "-c", "'" + strings.Join(args, " ") + "'"} } @@ -455,7 +455,7 @@ func (inst *instance) serialPortArgs(replay bool) []string { } conAddr := fmt.Sprintf("%v.%v.%v.%s.port=1%s@%v-ssh-serialport.googleapis.com", inst.GCE.ProjectID, inst.GCE.ZoneID, inst.name, user, replayArg, inst.GCE.RegionID) - conArgs := append(vmimpl.SSHArgs(inst.debug, key, 9600), conAddr) + conArgs := append(vmimpl.SSHArgs(inst.debug, key, 9600, false), conAddr) // TODO(blackgnezdo): Remove this once ssh-serialport.googleapis.com stops using // host key algorithm: ssh-rsa. return append(conArgs, "-o", "HostKeyAlgorithms=+ssh-rsa") diff --git a/vm/isolated/isolated.go b/vm/isolated/isolated.go index 76d5284c0..51a995b72 100755 --- a/vm/isolated/isolated.go +++ b/vm/isolated/isolated.go @@ -34,6 +34,7 @@ type Config struct { USBDevNums []string `json:"usb_device_num"` // /sys/bus/usb/devices/ StartupScript string `json:"startup_script"` // script to execute after each startup Pstore bool `json:"pstore"` // use crashlogs from pstore + SystemSSHCfg bool `json:"system_ssh_cfg"` // whether to allow system-wide SSH configuration } type Pool struct { @@ -159,7 +160,7 @@ func (inst *instance) ssh(command string) error { } // TODO(dvyukov): who is closing rpipe? - args := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, inst.targetPort), + args := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), inst.sshUser+"@"+inst.targetAddr, command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) @@ -257,7 +258,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.os, inst.targetPort, nil, inst.cfg.SystemSSHCfg) } func (inst *instance) waitForReboot(timeout int) error { @@ -286,7 +287,7 @@ 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), + args := append(vmimpl.SCPArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), hostSrc, inst.sshUser+"@"+inst.targetAddr+":"+vmDst) cmd := osutil.Command("scp", args...) if inst.debug { @@ -315,7 +316,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.sshUser+"@"+inst.targetAddr) + args := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), + inst.sshUser+"@"+inst.targetAddr) dmesg, err := vmimpl.OpenRemoteConsole("ssh", args...) if err != nil { return nil, nil, err @@ -327,7 +329,7 @@ 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) + args = vmimpl.SSHArgsForward(inst.debug, inst.sshKey, inst.targetPort, inst.forwardPort, inst.cfg.SystemSSHCfg) if inst.cfg.Pstore { args = append(args, "-o", "ServerAliveInterval=6") args = append(args, "-o", "ServerAliveCountMax=5") @@ -360,7 +362,7 @@ 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), + args := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, inst.targetPort, inst.cfg.SystemSSHCfg), inst.sshUser+"@"+inst.targetAddr, "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 b3f1ca0bc..4b857066a 100644 --- a/vm/qemu/qemu.go +++ b/vm/qemu/qemu.go @@ -550,7 +550,7 @@ 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); err != nil { + inst.sshkey, inst.sshuser, inst.os, inst.port, inst.merger.Err, false); err != nil { bootOutputStop <- true <-bootOutputStop return vmimpl.MakeBootError(err, bootOutput) @@ -632,7 +632,7 @@ func (inst *instance) Copy(hostSrc string) (string, error) { inst.files[vmDst] = hostSrc } - args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, inst.port), + args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, inst.port, false), hostSrc, inst.sshuser+"@localhost:"+vmDst) if inst.debug { log.Logf(0, "running command: scp %#v", args) @@ -652,7 +652,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) + sshArgs := vmimpl.SSHArgsForward(inst.debug, inst.sshkey, inst.port, inst.forwardPort, false) args := strings.Split(command, " ") if bin := filepath.Base(args[0]); inst.target.HostFuzzer && (bin == "syz-fuzzer" || bin == "syz-execprog") { @@ -751,7 +751,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), inst.sshuser+"@localhost") + sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshkey, inst.port, false), inst.sshuser+"@localhost") return append(sshArgs, args...) } diff --git a/vm/vmimpl/util.go b/vm/vmimpl/util.go index 9a007b386..a04914e6d 100644 --- a/vm/vmimpl/util.go +++ b/vm/vmimpl/util.go @@ -23,7 +23,8 @@ func SleepInterruptible(d time.Duration) bool { } } -func WaitForSSH(debug bool, timeout time.Duration, addr, sshKey, sshUser, OS string, port int, stop chan error) error { +func WaitForSSH(debug bool, timeout time.Duration, addr, sshKey, sshUser, OS string, port int, stop chan error, + systemSSHCfg bool) error { pwd := "pwd" if OS == targets.Windows { pwd = "dir" @@ -38,7 +39,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), sshUser+"@"+addr, pwd) + args := append(SSHArgs(debug, sshKey, port, systemSSHCfg), sshUser+"@"+addr, pwd) if debug { log.Logf(0, "running ssh: %#v", args) } @@ -55,28 +56,31 @@ func WaitForSSH(debug bool, timeout time.Duration, addr, sshKey, sshUser, OS str } } -func SSHArgs(debug bool, sshKey string, port int) []string { - return sshArgs(debug, sshKey, "-p", port, 0) +func SSHArgs(debug bool, sshKey string, port int, systemSSHCfg bool) []string { + return sshArgs(debug, sshKey, "-p", port, 0, systemSSHCfg) } -func SSHArgsForward(debug bool, sshKey string, port, forwardPort int) []string { - return sshArgs(debug, sshKey, "-p", port, forwardPort) +func SSHArgsForward(debug bool, sshKey string, port, forwardPort int, systemSSHCfg bool) []string { + return sshArgs(debug, sshKey, "-p", port, forwardPort, systemSSHCfg) } -func SCPArgs(debug bool, sshKey string, port int) []string { - return sshArgs(debug, sshKey, "-P", port, 0) +func SCPArgs(debug bool, sshKey string, port int, systemSSHCfg bool) []string { + return sshArgs(debug, sshKey, "-P", port, 0, systemSSHCfg) } -func sshArgs(debug bool, sshKey, portArg string, port, forwardPort int) []string { - args := []string{ - portArg, fmt.Sprint(port), - "-F", "/dev/null", - "-o", "UserKnownHostsFile=/dev/null", +func sshArgs(debug bool, sshKey, portArg string, port, forwardPort int, systemSSHCfg bool) []string { + args := []string{portArg, fmt.Sprint(port)} + if !systemSSHCfg { + args = append(args, + "-F", "/dev/null", + "-o", "UserKnownHostsFile=/dev/null", + "-o", "IdentitiesOnly=yes") + } + args = append(args, "-o", "BatchMode=yes", - "-o", "IdentitiesOnly=yes", "-o", "StrictHostKeyChecking=no", "-o", "ConnectTimeout=10", - } + ) if sshKey != "" { args = append(args, "-i", sshKey) } diff --git a/vm/vmm/vmm.go b/vm/vmm/vmm.go index bcddc3af0..71dfd39b4 100644 --- a/vm/vmm/vmm.go +++ b/vm/vmm/vmm.go @@ -187,7 +187,7 @@ func (inst *instance) Boot() error { } if err := vmimpl.WaitForSSH(inst.debug, 20*time.Minute, inst.sshhost, - inst.sshkey, inst.sshuser, inst.os, inst.sshport, nil); err != nil { + inst.sshkey, inst.sshuser, inst.os, inst.sshport, nil, false); err != nil { out := <-inst.merger.Output return vmimpl.BootError{Title: err.Error(), Output: out} } @@ -239,7 +239,7 @@ 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), + args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, inst.sshport, false), hostSrc, inst.sshuser+"@"+inst.sshhost+":"+vmDst) if inst.debug { log.Logf(0, "running command: scp %#v", args) @@ -259,7 +259,7 @@ 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), + args := append(vmimpl.SSHArgs(inst.debug, inst.sshkey, inst.sshport, false), inst.sshuser+"@"+inst.sshhost, command) if inst.debug { log.Logf(0, "running command: ssh %#v", args) diff --git a/vm/vmware/vmware.go b/vm/vmware/vmware.go index ebfb995bb..4c05bac12 100644 --- a/vm/vmware/vmware.go +++ b/vm/vmware/vmware.go @@ -157,7 +157,7 @@ func (inst *instance) Copy(hostSrc string) (string, error) { base := filepath.Base(hostSrc) vmDst := filepath.Join("/", base) - args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, 22), + args := append(vmimpl.SCPArgs(inst.debug, inst.sshkey, 22, false), hostSrc, fmt.Sprintf("%v@%v:%v", inst.sshuser, inst.ipAddr, vmDst)) if inst.debug { @@ -186,7 +186,7 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin return nil, nil, err } - args := vmimpl.SSHArgs(inst.debug, inst.sshkey, 22) + args := vmimpl.SSHArgs(inst.debug, inst.sshkey, 22, false) // Forward target port as part of the ssh connection (reverse proxy) if inst.forwardPort != 0 { proxy := fmt.Sprintf("%v:127.0.0.1:%v", inst.forwardPort, inst.forwardPort) -- cgit mrf-deployment