diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2015-12-30 18:25:14 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2015-12-30 18:25:14 +0100 |
| commit | 43815ce761bed14a1c8d3b4a3a20d93d56deefb6 (patch) | |
| tree | 2cb064221a47db6f4140b0bf47af026acd5f7de6 | |
| parent | ddcd0929e3550ea0e376b0c73e50d617b40b9d50 (diff) | |
vm/local: revive local VM
| -rw-r--r-- | syz-manager/manager.go | 1 | ||||
| -rw-r--r-- | vm/local/local.go | 105 |
2 files changed, 106 insertions, 0 deletions
diff --git a/syz-manager/manager.go b/syz-manager/manager.go index a670b5e8f..11e824d17 100644 --- a/syz-manager/manager.go +++ b/syz-manager/manager.go @@ -25,6 +25,7 @@ import ( "github.com/google/syzkaller/sys" "github.com/google/syzkaller/vm" _ "github.com/google/syzkaller/vm/kvm" + _ "github.com/google/syzkaller/vm/local" _ "github.com/google/syzkaller/vm/qemu" ) diff --git a/vm/local/local.go b/vm/local/local.go new file mode 100644 index 000000000..acba16258 --- /dev/null +++ b/vm/local/local.go @@ -0,0 +1,105 @@ +// Copyright 2015 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +package local + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/google/syzkaller/fileutil" + "github.com/google/syzkaller/vm" +) + +func init() { + vm.Register("local", ctor) +} + +type instance struct { + cfg *vm.Config + closed chan bool + files map[string]string +} + +func ctor(cfg *vm.Config) (vm.Instance, error) { + inst := &instance{ + cfg: cfg, + closed: make(chan bool), + files: make(map[string]string), + } + return inst, nil +} + +func (inst *instance) HostAddr() string { + return "127.0.0.1" +} + +func (inst *instance) Close() { + close(inst.closed) + os.RemoveAll(inst.cfg.Workdir) +} + +func (inst *instance) Copy(hostSrc, vmDst string) error { + dst := filepath.Join(inst.cfg.Workdir, vmDst) + inst.files[vmDst] = dst + if err := fileutil.CopyFile(hostSrc, dst, false); err != nil { + return err + } + return os.Chmod(dst, 0777) +} + +func (inst *instance) Run(timeout time.Duration, command string) (<-chan []byte, <-chan error, error) { + for strings.Index(command, " ") != -1 { + command = strings.Replace(command, " ", " ", -1) + } + args := strings.Split(command, " ") + for i, arg := range args { + if inst.files[arg] != "" { + args[i] = inst.files[arg] + } + } + cmd := exec.Command(args[0], args[1:]...) + if err := cmd.Start(); err != nil { + return nil, nil, err + } + outputC := make(chan []byte, 10) + errorC := make(chan error, 2) + done := make(chan bool) + go func() { + errorC <- cmd.Wait() + close(done) + }() + go func() { + ticker := time.NewTicker(time.Second) + timeout := time.NewTicker(timeout) + for { + select { + case <-ticker.C: + select { + case outputC <- []byte{'.'}: + default: + } + case <-timeout.C: + errorC <- vm.TimeoutErr + cmd.Process.Kill() + ticker.Stop() + return + case <-done: + ticker.Stop() + timeout.Stop() + return + case <-inst.closed: + errorC <- fmt.Errorf("closed") + cmd.Process.Kill() + ticker.Stop() + timeout.Stop() + return + } + } + }() + return outputC, errorC, nil +} |
