aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-12-30 18:25:14 +0100
committerDmitry Vyukov <dvyukov@google.com>2015-12-30 18:25:14 +0100
commit43815ce761bed14a1c8d3b4a3a20d93d56deefb6 (patch)
tree2cb064221a47db6f4140b0bf47af026acd5f7de6
parentddcd0929e3550ea0e376b0c73e50d617b40b9d50 (diff)
vm/local: revive local VM
-rw-r--r--syz-manager/manager.go1
-rw-r--r--vm/local/local.go105
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
+}