aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--pkg/build/build.go2
-rw-r--r--pkg/build/openbsd.go64
-rwxr-xr-xtools/create-openbsd-vmm-worker.sh12
-rw-r--r--vm/gce/gce.go13
-rw-r--r--vm/gce/tar_go1.10.go14
-rw-r--r--vm/gce/tar_go1.9.go19
-rw-r--r--vm/vm.go2
-rw-r--r--vm/vmimpl/vmimpl.go4
-rw-r--r--vm/vmm/vmm.go10
9 files changed, 101 insertions, 39 deletions
diff --git a/pkg/build/build.go b/pkg/build/build.go
index 34015f3ab..7ce21e9b0 100644
--- a/pkg/build/build.go
+++ b/pkg/build/build.go
@@ -71,7 +71,7 @@ func getBuilder(targetOS, targetArch, vmType string) (builder, error) {
return fuchsia{}, nil
case targetOS == "akaros" && targetArch == "amd64" && vmType == "qemu":
return akaros{}, nil
- case targetOS == "openbsd" && targetArch == "amd64" && vmType == "vmm":
+ case targetOS == "openbsd" && targetArch == "amd64" && (vmType == "gce" || vmType == "vmm"):
return openbsd{}, nil
default:
return nil, fmt.Errorf("unsupported image type %v/%v/%v", targetOS, targetArch, vmType)
diff --git a/pkg/build/openbsd.go b/pkg/build/openbsd.go
index 1ec255ac6..319891cbc 100644
--- a/pkg/build/openbsd.go
+++ b/pkg/build/openbsd.go
@@ -10,6 +10,7 @@ import (
"strconv"
"time"
+ "github.com/google/syzkaller/pkg/log"
"github.com/google/syzkaller/pkg/osutil"
)
@@ -21,25 +22,29 @@ func (ctx openbsd) build(targetArch, vmType, kernelDir, outputDir, compiler, use
confDir := fmt.Sprintf("%v/sys/arch/%v/conf", kernelDir, targetArch)
compileDir := fmt.Sprintf("%v/sys/arch/%v/compile/%v", kernelDir, targetArch, kernelName)
- if err := ctx.configure(confDir, compileDir, kernelName); err != nil {
+ useGCE := vmType == "gce"
+ if err := ctx.configure(confDir, compileDir, kernelName, useGCE); err != nil {
return err
}
if err := ctx.make(compileDir, "all"); err != nil {
return err
}
-
- for src, dst := range map[string]string{
- filepath.Join(compileDir, "obj/bsd"): "kernel",
- filepath.Join(compileDir, "obj/bsd.gdb"): "obj/bsd.gdb",
- filepath.Join(userspaceDir, "image"): "image",
- filepath.Join(userspaceDir, "key"): "key",
+ for _, s := range []struct{ dir, src, dst string }{
+ {compileDir, "obj/bsd", "kernel"},
+ {compileDir, "obj/bsd.gdb", "obj/bsd.gdb"},
+ {userspaceDir, "image", "image"},
+ {userspaceDir, "key", "key"},
} {
- fullDst := filepath.Join(outputDir, dst)
- if err := osutil.CopyFile(src, fullDst); err != nil {
- return fmt.Errorf("failed to copy %v -> %v: %v", src, fullDst, err)
+ fullSrc := filepath.Join(s.dir, s.src)
+ fullDst := filepath.Join(outputDir, s.dst)
+ if err := osutil.CopyFile(fullSrc, fullDst); err != nil {
+ return fmt.Errorf("failed to copy %v -> %v: %v", fullSrc, fullDst, err)
}
}
+ if useGCE {
+ return CopyKernelToImage(outputDir)
+ }
return nil
}
@@ -47,11 +52,18 @@ func (ctx openbsd) clean(kernelDir string) error {
return ctx.make(kernelDir, "", "clean")
}
-func (ctx openbsd) configure(confDir, compileDir, kernelName string) error {
- conf := []byte(`
-include "arch/amd64/conf/GENERIC"
+func (ctx openbsd) configure(confDir, compileDir, kernelName string, useGCE bool) error {
+ baseConfig := "GENERIC"
+ if useGCE {
+ // GCE supports multiple CPUs.
+ // TODO(gnezdo): Switch to GENERIC.MP once kernel crash is solved.
+ // http://openbsd-archive.7691.n7.nabble.com/option-kcov-GENERIC-MP-gt-silent-crash-tc355807.html
+ baseConfig = "GENERIC"
+ }
+ conf := []byte(fmt.Sprintf(`
+include "arch/amd64/conf/%v"
pseudo-device kcov 1
-`)
+`, baseConfig))
if err := osutil.WriteFile(filepath.Join(confDir, kernelName), conf); err != nil {
return err
}
@@ -78,3 +90,27 @@ func (ctx openbsd) make(kernelDir string, args ...string) error {
_, err := osutil.RunCmd(10*time.Minute, kernelDir, "make", args...)
return err
}
+
+// The easiest way to make an openbsd image that boots the given
+// kernel on GCE is to simply overwrite it inside the disk image.
+// Ideally a user space tool capable of understanding FFS should
+// implement this directly, but vnd(4) device would do in a pinch.
+// Assumes that the outputDir contains the appropriately named files.
+func CopyKernelToImage(outputDir string) error {
+ script := `set -eux
+# Cleanup in case something failed before.
+doas umount /altroot || true
+doas vnconfig -u vnd0 || true
+
+doas /sbin/vnconfig vnd0 image
+doas mount /dev/vnd0a /altroot
+doas cp kernel /altroot/bsd
+doas umount /altroot
+doas vnconfig -u vnd0
+`
+ debugOut, err := osutil.RunCmd(10*time.Minute, outputDir, "/bin/sh", "-c", script)
+ if err != nil {
+ log.Logf(0, "Error copying kernel into image %v\n%v\n", outputDir, debugOut)
+ }
+ return err
+}
diff --git a/tools/create-openbsd-vmm-worker.sh b/tools/create-openbsd-vmm-worker.sh
index cce3ad8ef..1baa3c687 100755
--- a/tools/create-openbsd-vmm-worker.sh
+++ b/tools/create-openbsd-vmm-worker.sh
@@ -41,6 +41,10 @@ perl -i.bak -pne 's/^(ttyC.*)vt220.*/$1unknown off/' /etc/ttys
touch root/.hushlogin home/syzkaller/.hushlogin
EOF
+cat >etc/sysctl.conf <<EOF
+hw.smt=1
+EOF
+
cat >etc/installurl <<EOF
https://${MIRROR}/pub/OpenBSD
EOF
@@ -108,15 +112,15 @@ growisofs -M "${ISO_PATCHED}" -l -R -graft-points \
/etc/random.seed=random.seed
# Initialize disk image.
-rm -f worker_disk.qcow2
-qemu-img create -f qcow2 worker_disk.qcow2 1G
+rm -f worker_disk.raw
+qemu-img create -f raw worker_disk.raw 1G
# Run the installer to create the disk image.
expect 2>&1 <<EOF | tee install_log
set timeout 1800
spawn qemu-system-x86_64 -nographic -smp 2 \
- -drive if=virtio,file=worker_disk.qcow2,format=qcow2 -cdrom "${ISO_PATCHED}" \
+ -drive if=virtio,file=worker_disk.raw,format=raw -cdrom "${ISO_PATCHED}" \
-net nic,model=virtio -net user -boot once=d -m 4000 -enable-kvm
expect timeout { exit 1 } "boot>"
@@ -165,5 +169,5 @@ expect {
EOF
cat <<EOF
-Done: worker_disk.qcow2
+Done: worker_disk.raw
EOF
diff --git a/vm/gce/gce.go b/vm/gce/gce.go
index 52ea87a48..32f3e2947 100644
--- a/vm/gce/gce.go
+++ b/vm/gce/gce.go
@@ -100,7 +100,7 @@ func ctor(env *vmimpl.Env) (vmimpl.Pool, error) {
if cfg.GCEImage == "" {
cfg.GCEImage = env.Name
gcsImage := filepath.Join(cfg.GCSPath, env.Name+"-image.tar.gz")
- log.Logf(0, "uploading image to %v...", gcsImage)
+ log.Logf(0, "uploading image %v to %v...", env.Image, gcsImage)
if err := uploadImageToGCS(env.Image, gcsImage); err != nil {
return nil, err
}
@@ -436,15 +436,10 @@ func uploadImageToGCS(localImage, gcsImage string) error {
Mode: 0640,
Size: localStat.Size(),
ModTime: time.Now(),
- // This is hacky but we actually need these large uids.
- // GCE understands only the old GNU tar format and
- // there is no direct way to force tar package to use GNU format.
- // But these large numbers force tar to switch to GNU format.
- Uid: 100000000,
- Gid: 100000000,
- Uname: "syzkaller",
- Gname: "syzkaller",
+ Uname: "syzkaller",
+ Gname: "syzkaller",
}
+ setGNUFormat(tarHeader)
if err := tarWriter.WriteHeader(tarHeader); err != nil {
return fmt.Errorf("failed to write image tar header: %v", err)
}
diff --git a/vm/gce/tar_go1.10.go b/vm/gce/tar_go1.10.go
new file mode 100644
index 000000000..88a5d1fda
--- /dev/null
+++ b/vm/gce/tar_go1.10.go
@@ -0,0 +1,14 @@
+// Copyright 2018 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.
+
+// +build go1.10
+
+package gce
+
+import (
+ "archive/tar"
+)
+
+func setGNUFormat(hdr *tar.Header) {
+ hdr.Format = tar.FormatGNU
+}
diff --git a/vm/gce/tar_go1.9.go b/vm/gce/tar_go1.9.go
new file mode 100644
index 000000000..a26ecbdd5
--- /dev/null
+++ b/vm/gce/tar_go1.9.go
@@ -0,0 +1,19 @@
+// Copyright 2018 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.
+
+// +build !go1.10
+
+package gce
+
+import (
+ "archive/tar"
+)
+
+func setGNUFormat(hdr *tar.Header) {
+ // This is hacky but we actually need these large uids.
+ // GCE understands only the old GNU tar format and prior to Go 1.10
+ // there is no direct way to force tar package to use GNU format.
+ // But these large numbers force tar to switch to GNU format.
+ hdr.Uid = 100000000
+ hdr.Gid = 100000000
+}
diff --git a/vm/vm.go b/vm/vm.go
index 0a6114790..ad6f4c6f4 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -54,7 +54,7 @@ type BootErrorer interface {
// (i.e. creation of instances out-of-thin-air). Overcommit is used during image
// and patch testing in syz-ci when it just asks for more than specified in config
// instances. Generally virtual machines (qemu, gce) support overcommit,
-// while physical machines (adb, isolated) do not. Strictly saying, we should
+// while physical machines (adb, isolated) do not. Strictly speaking, we should
// never use overcommit and use only what's specified in config, because we
// override resource limits specified in config (e.g. can OOM). But it works and
// makes lots of things much simpler.
diff --git a/vm/vmimpl/vmimpl.go b/vm/vmimpl/vmimpl.go
index e9ac59dd6..7831a0bef 100644
--- a/vm/vmimpl/vmimpl.go
+++ b/vm/vmimpl/vmimpl.go
@@ -33,8 +33,8 @@ type Instance interface {
// Copy copies a hostSrc file into VM and returns file name in VM.
Copy(hostSrc string) (string, error)
- // Forward setups forwarding from within VM to host port port
- // and returns address to use in VM.
+ // Forward sets up forwarding from within VM to the given tcp
+ // port on the host and returns the address to use in VM.
Forward(port int) (string, error)
// Run runs cmd inside of the VM (think of ssh cmd).
diff --git a/vm/vmm/vmm.go b/vm/vmm/vmm.go
index 72ee49304..f29cd5098 100644
--- a/vm/vmm/vmm.go
+++ b/vm/vmm/vmm.go
@@ -125,18 +125,12 @@ func (pool *Pool) Create(workdir string, index int) (vmimpl.Instance, error) {
return nil, err
}
- closeInst := inst
- defer func() {
- if closeInst != nil {
- closeInst.Close()
- }
- }()
-
if err := inst.Boot(); err != nil {
+ // Cleans up if Boot fails.
+ inst.Close()
return nil, err
}
- closeInst = nil
return inst, nil
}