github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/vm/vmimpl/util.go (about)

     1  // Copyright 2017 syzkaller project authors. All rights reserved.
     2  // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
     3  
     4  package vmimpl
     5  
     6  import (
     7  	"fmt"
     8  	"time"
     9  
    10  	"github.com/google/syzkaller/pkg/log"
    11  	"github.com/google/syzkaller/pkg/osutil"
    12  	"github.com/google/syzkaller/sys/targets"
    13  )
    14  
    15  // Sleep for d.
    16  // If shutdown is in progress, return false prematurely.
    17  func SleepInterruptible(d time.Duration) bool {
    18  	select {
    19  	case <-time.After(d):
    20  		return true
    21  	case <-Shutdown:
    22  		return false
    23  	}
    24  }
    25  
    26  type SSHOptions struct {
    27  	Addr string
    28  	Port int
    29  	User string
    30  	Key  string
    31  }
    32  
    33  func WaitForSSH(timeout time.Duration, opts SSHOptions, OS string, stop chan error, systemSSHCfg, debug bool) error {
    34  	pwd := "pwd"
    35  	if OS == targets.Windows {
    36  		pwd = "dir"
    37  	}
    38  	startTime := time.Now()
    39  	SleepInterruptible(5 * time.Second)
    40  	for {
    41  		select {
    42  		case <-time.After(5 * time.Second):
    43  		case err := <-stop:
    44  			return err
    45  		case <-Shutdown:
    46  			return fmt.Errorf("shutdown in progress")
    47  		}
    48  		args := append(SSHArgs(debug, opts.Key, opts.Port, systemSSHCfg), opts.User+"@"+opts.Addr, pwd)
    49  		if debug {
    50  			log.Logf(0, "running ssh: %#v", args)
    51  		}
    52  		_, err := osutil.RunCmd(time.Minute, "", "ssh", args...)
    53  		if err == nil {
    54  			return nil
    55  		}
    56  		if debug {
    57  			log.Logf(0, "ssh failed: %v", err)
    58  		}
    59  		if time.Since(startTime) > timeout {
    60  			return &osutil.VerboseError{
    61  				Err:    ErrCantSSH,
    62  				Output: []byte(err.Error()),
    63  			}
    64  		}
    65  	}
    66  }
    67  
    68  var ErrCantSSH = fmt.Errorf("can't ssh into the instance")
    69  
    70  func SSHArgs(debug bool, sshKey string, port int, systemSSHCfg bool) []string {
    71  	return sshArgs(debug, sshKey, "-p", port, 0, systemSSHCfg)
    72  }
    73  
    74  func SSHArgsForward(debug bool, sshKey string, port, forwardPort int, systemSSHCfg bool) []string {
    75  	return sshArgs(debug, sshKey, "-p", port, forwardPort, systemSSHCfg)
    76  }
    77  
    78  func SCPArgs(debug bool, sshKey string, port int, systemSSHCfg bool) []string {
    79  	return sshArgs(debug, sshKey, "-P", port, 0, systemSSHCfg)
    80  }
    81  
    82  func sshArgs(debug bool, sshKey, portArg string, port, forwardPort int, systemSSHCfg bool) []string {
    83  	args := []string{portArg, fmt.Sprint(port)}
    84  	if !systemSSHCfg {
    85  		args = append(args,
    86  			"-F", "/dev/null",
    87  			"-o", "UserKnownHostsFile=/dev/null",
    88  			"-o", "IdentitiesOnly=yes")
    89  	}
    90  	args = append(args,
    91  		"-o", "BatchMode=yes",
    92  		"-o", "StrictHostKeyChecking=no",
    93  		"-o", "ConnectTimeout=10",
    94  	)
    95  	if sshKey != "" {
    96  		args = append(args, "-i", sshKey)
    97  	}
    98  	if forwardPort != 0 {
    99  		// Forward target port as part of the ssh connection (reverse proxy).
   100  		args = append(args, "-R", fmt.Sprintf("%v:127.0.0.1:%v", forwardPort, forwardPort))
   101  	}
   102  	if debug {
   103  		args = append(args, "-v")
   104  	}
   105  	return args
   106  }