mirror of
https://github.com/reactos/syzkaller.git
synced 2024-11-23 11:29:46 +00:00
vm/gce: windows support
Support custom pre-created images. Support non-root user. Use dir instead of pwd on windows. Don't use sudo on windows.
This commit is contained in:
parent
fd98417f4d
commit
9fc15c7ea3
@ -27,7 +27,8 @@ type Config struct {
|
||||
Kernel_Src string // kernel source directory
|
||||
Tag string // arbitrary optional tag that is saved along with crash reports (e.g. branch/commit)
|
||||
Image string // linux image for VMs
|
||||
Sshkey string // root ssh key for the image (may be empty for some VM types)
|
||||
Sshkey string // ssh key for the image (may be empty for some VM types)
|
||||
Ssh_User string // ssh user ("root" by default)
|
||||
|
||||
Hub_Client string
|
||||
Hub_Addr string
|
||||
@ -81,6 +82,7 @@ func LoadFile(filename string) (*Config, error) {
|
||||
|
||||
func DefaultValues() *Config {
|
||||
return &Config{
|
||||
Ssh_User: "root",
|
||||
Cover: true,
|
||||
Reproduce: true,
|
||||
Sandbox: "setuid",
|
||||
@ -271,7 +273,8 @@ func CreateVMEnv(cfg *Config, debug bool) *vm.Env {
|
||||
Arch: cfg.TargetVMArch,
|
||||
Workdir: cfg.Workdir,
|
||||
Image: cfg.Image,
|
||||
Sshkey: cfg.Sshkey,
|
||||
SshKey: cfg.Sshkey,
|
||||
SshUser: cfg.Ssh_User,
|
||||
Debug: debug,
|
||||
Config: cfg.VM,
|
||||
}
|
||||
|
@ -39,16 +39,17 @@ type Config struct {
|
||||
Count int // number of VMs to use
|
||||
Machine_Type string // GCE machine type (e.g. "n1-highcpu-2")
|
||||
GCS_Path string // GCS path to upload image
|
||||
GCE_Image string // Pre-created GCE image to use
|
||||
}
|
||||
|
||||
type Pool struct {
|
||||
env *vmimpl.Env
|
||||
cfg *Config
|
||||
GCE *gce.Context
|
||||
gceImage string
|
||||
env *vmimpl.Env
|
||||
cfg *Config
|
||||
GCE *gce.Context
|
||||
}
|
||||
|
||||
type instance struct {
|
||||
env *vmimpl.Env
|
||||
cfg *Config
|
||||
GCE *gce.Context
|
||||
debug bool
|
||||
@ -84,9 +85,12 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
|
||||
if cfg.Machine_Type == "" {
|
||||
return nil, fmt.Errorf("machine_type parameter is empty")
|
||||
}
|
||||
if cfg.GCS_Path == "" {
|
||||
if cfg.GCE_Image == "" && cfg.GCS_Path == "" {
|
||||
return nil, fmt.Errorf("gcs_path parameter is empty")
|
||||
}
|
||||
if cfg.GCE_Image != "" && env.Image != "" {
|
||||
return nil, fmt.Errorf("both image and gce_image are specified")
|
||||
}
|
||||
|
||||
GCE, err := gce.NewContext()
|
||||
if err != nil {
|
||||
@ -95,24 +99,25 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
|
||||
Logf(0, "GCE initialized: running on %v, internal IP %v, project %v, zone %v",
|
||||
GCE.Instance, GCE.InternalIP, GCE.ProjectID, GCE.ZoneID)
|
||||
|
||||
gcsImage := filepath.Join(cfg.GCS_Path, env.Name+"-image.tar.gz")
|
||||
Logf(0, "uploading image to %v...", gcsImage)
|
||||
if err := uploadImageToGCS(env.Image, gcsImage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gceImage := env.Name
|
||||
Logf(0, "creating GCE image %v...", gceImage)
|
||||
if err := GCE.DeleteImage(gceImage); err != nil {
|
||||
return nil, fmt.Errorf("failed to delete GCE image: %v", err)
|
||||
}
|
||||
if err := GCE.CreateImage(gceImage, gcsImage); err != nil {
|
||||
return nil, fmt.Errorf("failed to create GCE image: %v", err)
|
||||
if cfg.GCE_Image == "" {
|
||||
cfg.GCE_Image = env.Name
|
||||
gcsImage := filepath.Join(cfg.GCS_Path, env.Name+"-image.tar.gz")
|
||||
Logf(0, "uploading image to %v...", gcsImage)
|
||||
if err := uploadImageToGCS(env.Image, gcsImage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Logf(0, "creating GCE image %v...", cfg.GCE_Image)
|
||||
if err := GCE.DeleteImage(cfg.GCE_Image); err != nil {
|
||||
return nil, fmt.Errorf("failed to delete GCE image: %v", err)
|
||||
}
|
||||
if err := GCE.CreateImage(cfg.GCE_Image, gcsImage); err != nil {
|
||||
return nil, fmt.Errorf("failed to create GCE image: %v", err)
|
||||
}
|
||||
}
|
||||
pool := &Pool{
|
||||
cfg: cfg,
|
||||
env: env,
|
||||
GCE: GCE,
|
||||
gceImage: gceImage,
|
||||
cfg: cfg,
|
||||
env: env,
|
||||
GCE: GCE,
|
||||
}
|
||||
return pool, nil
|
||||
}
|
||||
@ -139,7 +144,7 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
|
||||
return nil, err
|
||||
}
|
||||
Logf(0, "creating instance: %v", name)
|
||||
ip, err := pool.GCE.CreateInstance(name, pool.cfg.Machine_Type, pool.gceImage, string(gceKeyPub))
|
||||
ip, err := pool.GCE.CreateInstance(name, pool.cfg.Machine_Type, pool.cfg.GCE_Image, string(gceKeyPub))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -150,19 +155,20 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
|
||||
pool.GCE.DeleteInstance(name, true)
|
||||
}
|
||||
}()
|
||||
sshKey := pool.env.Sshkey
|
||||
sshUser := "root"
|
||||
sshKey := pool.env.SshKey
|
||||
sshUser := pool.env.SshUser
|
||||
if sshKey == "" {
|
||||
// Assuming image supports GCE ssh fanciness.
|
||||
sshKey = gceKey
|
||||
sshUser = "syzkaller"
|
||||
}
|
||||
Logf(0, "wait instance to boot: %v (%v)", name, ip)
|
||||
if err := waitInstanceBoot(pool.env.Debug, ip, sshKey, sshUser); err != nil {
|
||||
if err := pool.waitInstanceBoot(ip, sshKey, sshUser); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ok = true
|
||||
inst := &instance{
|
||||
env: pool.env,
|
||||
cfg: pool.cfg,
|
||||
debug: pool.env.Debug,
|
||||
GCE: pool.GCE,
|
||||
@ -272,8 +278,10 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin
|
||||
sshRpipe.Close()
|
||||
return nil, nil, err
|
||||
}
|
||||
if inst.sshUser != "root" {
|
||||
command = fmt.Sprintf("sudo bash -c '%v'", command)
|
||||
if inst.env.OS == "linux" {
|
||||
if inst.sshUser != "root" {
|
||||
command = fmt.Sprintf("sudo bash -c '%v'", command)
|
||||
}
|
||||
}
|
||||
args := append(sshArgs(inst.debug, inst.sshKey, "-p", 22), inst.sshUser+"@"+inst.name, command)
|
||||
ssh := exec.Command("ssh", args...)
|
||||
@ -334,13 +342,17 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin
|
||||
return merger.Output, errc, nil
|
||||
}
|
||||
|
||||
func waitInstanceBoot(debug bool, ip, sshKey, sshUser string) error {
|
||||
func (pool *Pool) waitInstanceBoot(ip, sshKey, sshUser string) error {
|
||||
pwd := "pwd"
|
||||
if pool.env.OS == "windows" {
|
||||
pwd = "dir"
|
||||
}
|
||||
for i := 0; i < 100; i++ {
|
||||
if !vmimpl.SleepInterruptible(5 * time.Second) {
|
||||
return fmt.Errorf("shutdown in progress")
|
||||
}
|
||||
args := append(sshArgs(debug, sshKey, "-p", 22), sshUser+"@"+ip, "pwd")
|
||||
if _, err := runCmd(debug, "ssh", args...); err == nil {
|
||||
args := append(sshArgs(pool.env.Debug, sshKey, "-p", 22), sshUser+"@"+ip, pwd)
|
||||
if _, err := runCmd(pool.env.Debug, "ssh", args...); err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -425,7 +437,7 @@ func sshArgs(debug bool, sshKey, portArg string, port int) []string {
|
||||
"-o", "BatchMode=yes",
|
||||
"-o", "IdentitiesOnly=yes",
|
||||
"-o", "StrictHostKeyChecking=no",
|
||||
"-o", "ConnectTimeout=5",
|
||||
"-o", "ConnectTimeout=10",
|
||||
}
|
||||
if debug {
|
||||
args = append(args, "-v")
|
||||
|
@ -54,8 +54,8 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
|
||||
return nil, fmt.Errorf("config param target_dir is empty")
|
||||
}
|
||||
// sshkey is optional
|
||||
if env.Sshkey != "" && !osutil.IsExist(env.Sshkey) {
|
||||
return nil, fmt.Errorf("ssh key '%v' does not exist", env.Sshkey)
|
||||
if env.SshKey != "" && !osutil.IsExist(env.SshKey) {
|
||||
return nil, fmt.Errorf("ssh key '%v' does not exist", env.SshKey)
|
||||
}
|
||||
if env.Debug {
|
||||
cfg.Targets = cfg.Targets[:1]
|
||||
@ -74,10 +74,10 @@ func (pool *Pool) Count() int {
|
||||
func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
|
||||
inst := &instance{
|
||||
cfg: pool.cfg,
|
||||
target: pool.cfg.Targets[index],
|
||||
target: pool.env.SshUser + "@" + pool.cfg.Targets[index],
|
||||
closed: make(chan bool),
|
||||
debug: pool.env.Debug,
|
||||
sshkey: pool.env.Sshkey,
|
||||
sshkey: pool.env.SshKey,
|
||||
}
|
||||
closeInst := inst
|
||||
defer func() {
|
||||
@ -120,7 +120,7 @@ func (inst *instance) ssh(command string) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args := append(inst.sshArgs("-p"), "root@"+inst.target, command)
|
||||
args := append(inst.sshArgs("-p"), inst.target, command)
|
||||
if inst.debug {
|
||||
Logf(0, "running command: ssh %#v", args)
|
||||
}
|
||||
@ -230,7 +230,7 @@ func (inst *instance) Copy(hostSrc string) (string, error) {
|
||||
baseName := filepath.Base(hostSrc)
|
||||
vmDst := filepath.Join(inst.cfg.Target_Dir, baseName)
|
||||
inst.ssh("pkill -9 '" + baseName + "'; rm -f '" + vmDst + "'")
|
||||
args := append(inst.sshArgs("-P"), hostSrc, "root@"+inst.target+":"+vmDst)
|
||||
args := append(inst.sshArgs("-P"), hostSrc, inst.target+":"+vmDst)
|
||||
cmd := exec.Command("scp", args...)
|
||||
if inst.debug {
|
||||
Logf(0, "running command: scp %#v", args)
|
||||
@ -257,7 +257,7 @@ 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(inst.sshArgs("-p"), "root@"+inst.target)
|
||||
args := append(inst.sshArgs("-p"), inst.target)
|
||||
dmesg, err := vmimpl.OpenRemoteConsole("ssh", args...)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
@ -275,7 +275,7 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin
|
||||
proxy := fmt.Sprintf("%v:127.0.0.1:%v", inst.port, inst.port)
|
||||
args = append(args, "-R", proxy)
|
||||
}
|
||||
args = append(args, "root@"+inst.target, "cd "+inst.cfg.Target_Dir+" && exec "+command)
|
||||
args = append(args, inst.target, "cd "+inst.cfg.Target_Dir+" && exec "+command)
|
||||
Logf(0, "running command: ssh %#v", args)
|
||||
if inst.debug {
|
||||
Logf(0, "running command: ssh %#v", args)
|
||||
|
@ -51,6 +51,7 @@ type instance struct {
|
||||
debug bool
|
||||
workdir string
|
||||
sshkey string
|
||||
sshuser string
|
||||
port int
|
||||
rpipe io.ReadCloser
|
||||
wpipe io.WriteCloser
|
||||
@ -118,8 +119,8 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
|
||||
if !osutil.IsExist(env.Image) {
|
||||
return nil, fmt.Errorf("image file '%v' does not exist", env.Image)
|
||||
}
|
||||
if !osutil.IsExist(env.Sshkey) {
|
||||
return nil, fmt.Errorf("ssh key '%v' does not exist", env.Sshkey)
|
||||
if !osutil.IsExist(env.SshKey) {
|
||||
return nil, fmt.Errorf("ssh key '%v' does not exist", env.SshKey)
|
||||
}
|
||||
}
|
||||
if cfg.Cpu <= 0 || cfg.Cpu > 1024 {
|
||||
@ -142,9 +143,11 @@ func (pool *Pool) Count() int {
|
||||
}
|
||||
|
||||
func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
|
||||
sshkey := pool.env.Sshkey
|
||||
sshkey := pool.env.SshKey
|
||||
sshuser := pool.env.SshUser
|
||||
if pool.env.Image == "9p" {
|
||||
sshkey = filepath.Join(workdir, "key")
|
||||
sshuser = "root"
|
||||
keygen := exec.Command("ssh-keygen", "-t", "rsa", "-b", "2048", "-N", "", "-C", "", "-f", sshkey)
|
||||
if out, err := keygen.CombinedOutput(); err != nil {
|
||||
return nil, fmt.Errorf("failed to execute ssh-keygen: %v\n%s", err, out)
|
||||
@ -156,7 +159,7 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
|
||||
}
|
||||
|
||||
for i := 0; ; i++ {
|
||||
inst, err := pool.ctor(workdir, sshkey, index)
|
||||
inst, err := pool.ctor(workdir, sshkey, sshuser, index)
|
||||
if err == nil {
|
||||
return inst, nil
|
||||
}
|
||||
@ -167,13 +170,14 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (pool *Pool) ctor(workdir, sshkey string, index int) (vmimpl.Instance, error) {
|
||||
func (pool *Pool) ctor(workdir, sshkey, sshuser string, index int) (vmimpl.Instance, error) {
|
||||
inst := &instance{
|
||||
cfg: pool.cfg,
|
||||
image: pool.env.Image,
|
||||
debug: pool.env.Debug,
|
||||
workdir: workdir,
|
||||
sshkey: sshkey,
|
||||
sshuser: sshuser,
|
||||
}
|
||||
closeInst := inst
|
||||
defer func() {
|
||||
@ -383,7 +387,7 @@ func (inst *instance) Copy(hostSrc string) (string, error) {
|
||||
basePath = "/tmp"
|
||||
}
|
||||
vmDst := filepath.Join(basePath, filepath.Base(hostSrc))
|
||||
args := append(inst.sshArgs("-P"), hostSrc, "root@localhost:"+vmDst)
|
||||
args := append(inst.sshArgs("-P"), hostSrc, inst.sshuser+"@localhost:"+vmDst)
|
||||
cmd := exec.Command("scp", args...)
|
||||
if inst.debug {
|
||||
Logf(0, "running command: scp %#v", args)
|
||||
@ -416,7 +420,7 @@ func (inst *instance) Run(timeout time.Duration, stop <-chan bool, command strin
|
||||
}
|
||||
inst.merger.Add("ssh", rpipe)
|
||||
|
||||
args := append(inst.sshArgs("-p"), "root@localhost", command)
|
||||
args := append(inst.sshArgs("-p"), inst.sshuser+"@localhost", command)
|
||||
if inst.debug {
|
||||
Logf(0, "running command: ssh %#v", args)
|
||||
}
|
||||
|
@ -50,7 +50,8 @@ type Env struct {
|
||||
Arch string // target arch
|
||||
Workdir string
|
||||
Image string
|
||||
Sshkey string
|
||||
SshKey string
|
||||
SshUser string
|
||||
Debug bool
|
||||
Config []byte // json-serialized VM-type-specific config
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user