diff options
| -rw-r--r-- | vm/cuttlefish/cuttlefish.go | 42 | ||||
| -rw-r--r-- | vm/gce/gce.go | 77 |
2 files changed, 67 insertions, 52 deletions
diff --git a/vm/cuttlefish/cuttlefish.go b/vm/cuttlefish/cuttlefish.go index ccea7c7e7..f6f61ee16 100644 --- a/vm/cuttlefish/cuttlefish.go +++ b/vm/cuttlefish/cuttlefish.go @@ -15,13 +15,15 @@ import ( "path/filepath" "time" - "github.com/google/syzkaller/pkg/log" + "github.com/google/syzkaller/pkg/osutil" "github.com/google/syzkaller/pkg/report" + "github.com/google/syzkaller/vm/gce" "github.com/google/syzkaller/vm/vmimpl" ) const ( - deviceRoot = "/data/fuzz" + deviceRoot = "/data/fuzz" + consoleReadCmd = "tail -f cuttlefish/instances/cvd-1/kernel.log" ) func init() { @@ -30,16 +32,19 @@ func init() { type Pool struct { env *vmimpl.Env - gcePool vmimpl.Pool + gcePool *gce.Pool } type instance struct { + name string + sshKey string + sshUser string debug bool gceInst vmimpl.Instance } func ctor(env *vmimpl.Env) (vmimpl.Pool, error) { - gcePool, err := vmimpl.Types["gce"].Ctor(env) + gcePool, err := gce.Ctor(env, consoleReadCmd) if err != nil { return nil, fmt.Errorf("failed to create underlying GCE pool: %s", err) } @@ -63,6 +68,9 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { } inst := &instance{ + name: fmt.Sprintf("%v-%v", pool.env.Name, index), + sshKey: pool.env.SSHKey, + sshUser: pool.env.SSHUser, debug: pool.env.Debug, gceInst: gceInst, } @@ -94,24 +102,18 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { return inst, nil } -func (inst *instance) runOnHost(timeout time.Duration, cmd string) error { - outc, errc, err := inst.gceInst.Run(timeout, nil, cmd) - if err != nil { - return fmt.Errorf("failed to run command: %s", err) +func (inst *instance) sshArgs(command string) []string { + sshArgs := append(vmimpl.SSHArgs(inst.debug, inst.sshKey, 22), inst.sshUser+"@"+inst.name) + if inst.sshUser != "root" { + return append(sshArgs, "sudo", "bash", "-c", "'"+command+"'") } + return append(sshArgs, command) +} - for { - select { - case <-vmimpl.Shutdown: - return nil - case err := <-errc: - return err - case out, ok := <-outc: - if ok && inst.debug { - log.Logf(1, "%s", out) - } - } - } +func (inst *instance) runOnHost(timeout time.Duration, command string) error { + _, err := osutil.RunCmd(timeout, "/root", "ssh", inst.sshArgs(command)...) + + return err } func (inst *instance) Copy(hostSrc string) (string, error) { diff --git a/vm/gce/gce.go b/vm/gce/gce.go index ef213d12e..ba05af51b 100644 --- a/vm/gce/gce.go +++ b/vm/gce/gce.go @@ -49,26 +49,32 @@ type Config struct { } type Pool struct { - env *vmimpl.Env - cfg *Config - GCE *gce.Context + env *vmimpl.Env + cfg *Config + GCE *gce.Context + consoleReadCmd string // optional: command to read non-standard kernel console } type instance struct { - env *vmimpl.Env - cfg *Config - GCE *gce.Context - debug bool - name string - ip string - gceKey string // per-instance private ssh key associated with the instance - sshKey string // ssh key - sshUser string - closed chan bool - consolew io.WriteCloser + env *vmimpl.Env + cfg *Config + GCE *gce.Context + debug bool + name string + ip string + 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 } func ctor(env *vmimpl.Env) (vmimpl.Pool, error) { + return Ctor(env, "") +} + +func Ctor(env *vmimpl.Env, consoleReadCmd string) (*Pool, error) { if env.Name == "" { return nil, fmt.Errorf("config param name is empty (required for GCE)") } @@ -123,9 +129,10 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) { } } pool := &Pool{ - cfg: cfg, - env: env, - GCE: GCE, + cfg: cfg, + env: env, + GCE: GCE, + consoleReadCmd: consoleReadCmd, } return pool, nil } @@ -182,16 +189,17 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) { } ok = true 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, - closed: make(chan bool), + env: pool.env, + cfg: pool.cfg, + debug: pool.env.Debug, + GCE: pool.GCE, + name: name, + ip: ip, + gceKey: gceKey, + sshKey: sshKey, + sshUser: sshUser, + closed: make(chan bool), + consoleReadCmd: pool.consoleReadCmd, } return inst, nil } @@ -224,11 +232,16 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin return nil, nil, err } - conAddr := fmt.Sprintf("%v.%v.%v.syzkaller.port=1@ssh-serialport.googleapis.com", - inst.GCE.ProjectID, inst.GCE.ZoneID, inst.name) - conArgs := append(vmimpl.SSHArgs(inst.debug, inst.gceKey, 9600), conAddr) - // TODO: remove this later (see also a comment in getSerialPortOutput). - conArgs = append(conArgs, "-o", "HostKeyAlgorithms=+ssh-rsa") + var conArgs []string + if inst.consoleReadCmd == "" { + conAddr := fmt.Sprintf("%v.%v.%v.syzkaller.port=1@ssh-serialport.googleapis.com", + inst.GCE.ProjectID, inst.GCE.ZoneID, inst.name) + conArgs = append(vmimpl.SSHArgs(inst.debug, inst.gceKey, 9600), conAddr) + // TODO: remove this later (see also a comment in getSerialPortOutput). + conArgs = append(conArgs, "-o", "HostKeyAlgorithms=+ssh-rsa") + } else { + conArgs = inst.sshArgs(inst.consoleReadCmd) + } con := osutil.Command("ssh", conArgs...) con.Env = []string{} con.Stdout = conWpipe |
