aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/kernel
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-06-01 15:54:10 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-06-03 10:41:09 +0200
commit1a7e5fb38dee3b87db687c243038556c536386dd (patch)
tree4296ed991cbc4db64658c2ebe997bfae3a5f71cb /pkg/kernel
parent48d4af340f9b30c659aae910419aea6d666a7ae0 (diff)
pkg/kernel: add new package
Move functionality to build kernel/image from syz-gce to a separate package.
Diffstat (limited to 'pkg/kernel')
-rw-r--r--pkg/kernel/generated.go84
-rw-r--r--pkg/kernel/kernel.go74
2 files changed, 158 insertions, 0 deletions
diff --git a/pkg/kernel/generated.go b/pkg/kernel/generated.go
new file mode 100644
index 000000000..08d08e474
--- /dev/null
+++ b/pkg/kernel/generated.go
@@ -0,0 +1,84 @@
+// AUTOGENERATED FILE
+
+package kernel
+
+const createImageScript = `#!/bin/bash
+
+
+set -eux
+
+if [ ! -e $1/sbin/init ]; then
+ echo "usage: create-gce-image.sh /dir/with/user/space/system /path/to/bzImage /path/to/vmlinux 'image tag'"
+ exit 1
+fi
+
+if [ "$(basename $2)" != "bzImage" ]; then
+ echo "usage: create-gce-image.sh /dir/with/user/space/system /path/to/bzImage /path/to/vmlinux 'image tag'"
+ exit 1
+fi
+
+if [ "$(basename $3)" != "vmlinux" ]; then
+ echo "usage: create-gce-image.sh /dir/with/user/space/system /path/to/bzImage /path/to/vmlinux 'image tag'"
+ exit 1
+fi
+
+sudo umount disk.mnt || true
+sudo qemu-nbd -d /dev/nbd0 || true
+rm -rf disk.mnt disk.raw tag obj || true
+
+sudo modprobe nbd
+fallocate -l 2G disk.raw
+sudo qemu-nbd -c /dev/nbd0 --format=raw disk.raw
+mkdir -p disk.mnt
+echo -en "o\nn\np\n1\n2048\n\na\n1\nw\n" | sudo fdisk /dev/nbd0
+until [ -e /dev/nbd0p1 ]; do sleep 1; done
+sudo mkfs.ext4 /dev/nbd0p1
+sudo mount /dev/nbd0p1 disk.mnt
+sudo cp -a $1/. disk.mnt/.
+sudo cp $2 disk.mnt/vmlinuz
+sudo sed -i "/^root/ { s/:x:/::/ }" disk.mnt/etc/passwd
+echo "T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100" | sudo tee -a disk.mnt/etc/inittab
+echo -en "auto lo\niface lo inet loopback\nauto eth0\niface eth0 inet dhcp\n" | sudo tee disk.mnt/etc/network/interfaces
+echo "debugfs /sys/kernel/debug debugfs defaults 0 0" | sudo tee -a disk.mnt/etc/fstab
+echo "kernel.printk = 7 4 1 3" | sudo tee -a disk.mnt/etc/sysctl.conf
+echo "debug.exception-trace = 0" | sudo tee -a disk.mnt/etc/sysctl.conf
+echo "net.core.bpf_jit_enable = 1" | sudo tee -a disk.mnt/etc/sysctl.conf
+echo "net.core.bpf_jit_harden = 2" | sudo tee -a disk.mnt/etc/sysctl.conf
+echo "net.ipv4.ping_group_range = 0 65535" | sudo tee -a disk.mnt/etc/sysctl.conf
+echo -en "127.0.0.1\tlocalhost\n" | sudo tee disk.mnt/etc/hosts
+echo "nameserver 8.8.8.8" | sudo tee -a disk.mnt/etc/resolve.conf
+echo "ClientAliveInterval 420" | sudo tee -a disk.mnt/etc/ssh/sshd_config
+echo "syzkaller" | sudo tee disk.mnt/etc/hostname
+rm -f key key.pub
+ssh-keygen -f key -t rsa -N ""
+sudo mkdir -p disk.mnt/root/.ssh
+sudo cp key.pub disk.mnt/root/.ssh/authorized_keys
+sudo chown root disk.mnt/root/.ssh/authorized_keys
+sudo mkdir -p disk.mnt/boot/grub
+cat << EOF | sudo tee disk.mnt/boot/grub/grub.cfg
+terminal_input console
+terminal_output console
+set timeout=0
+menuentry 'linux' --class gnu-linux --class gnu --class os {
+ insmod vbe
+ insmod vga
+ insmod video_bochs
+ insmod video_cirrus
+ insmod gzio
+ insmod part_msdos
+ insmod ext2
+ set root='(hd0,1)'
+ linux /vmlinuz root=/dev/sda1 console=ttyS0 earlyprintk=serial vsyscall=native rodata=n ftrace_dump_on_oops=orig_cpu oops=panic panic_on_warn=1 panic=86400 kvm-intel.nested=1 kvm-intel.unrestricted_guest=1 kvm-intel.vmm_exclusive=1 kvm-intel.fasteoi=1 kvm-intel.ept=1 kvm-intel.flexpriority=1 kvm-intel.vpid=1 kvm-intel.emulate_invalid_guest_state=1 kvm-intel.eptad=1 kvm-intel.enable_shadow_vmcs=1 kvm-intel.pml=1 kvm-intel.enable_apicv=1
+}
+EOF
+sudo grub-install --boot-directory=disk.mnt/boot --no-floppy /dev/nbd0
+sudo umount disk.mnt
+rm -rf disk.mnt
+sudo qemu-nbd -d /dev/nbd0
+tar -Szcf disk.tar.gz disk.raw
+mkdir -p obj
+cp $3 obj/
+echo -n "$4" > tag
+tar -czvf image.tar.gz disk.tar.gz key tag obj/vmlinux
+rm -rf tag obj
+`
diff --git a/pkg/kernel/kernel.go b/pkg/kernel/kernel.go
new file mode 100644
index 000000000..80a8e29c6
--- /dev/null
+++ b/pkg/kernel/kernel.go
@@ -0,0 +1,74 @@
+// Copyright 2017 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.
+
+//go:generate bash -c "echo -en '// AUTOGENERATED FILE\n\n' > generated.go"
+//go:generate bash -c "echo -en 'package kernel\n\n' >> generated.go"
+//go:generate bash -c "echo -en 'const createImageScript = `#!/bin/bash\n' >> generated.go"
+//go:generate bash -c "cat ../../tools/create-gce-image.sh | grep -v '#' >> generated.go"
+//go:generate bash -c "echo -en '`\n\n' >> generated.go"
+
+// Package kernel contains helper functions for working with Linux kernel
+// (building kernel/image).
+package kernel
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "runtime"
+ "strconv"
+ "time"
+
+ "github.com/google/syzkaller/pkg/osutil"
+)
+
+func Build(dir, compiler, config string) error {
+ const timeout = 10 * time.Minute // default timeout for command invocations
+ os.Remove(filepath.Join(dir, ".config"))
+ configFile := filepath.Join(dir, "syz.config")
+ if err := ioutil.WriteFile(configFile, []byte(config), 0600); err != nil {
+ return fmt.Errorf("failed to write config file: %v", err)
+ }
+ if _, err := osutil.RunCmd(timeout, dir, "make", "defconfig"); err != nil {
+ return err
+ }
+ if _, err := osutil.RunCmd(timeout, dir, "make", "kvmconfig"); err != nil {
+ return err
+ }
+ if _, err := osutil.RunCmd(timeout, dir, "scripts/kconfig/merge_config.sh", "-n", ".config", configFile); err != nil {
+ return err
+ }
+ if _, err := osutil.RunCmd(timeout, dir, "make", "olddefconfig"); err != nil {
+ return err
+ }
+ // Build of a large kernel can take a while on a 1 CPU VM.
+ if _, err := osutil.RunCmd(3*time.Hour, dir, "make", "-j", strconv.Itoa(runtime.NumCPU()*2), "CC="+compiler); err != nil {
+ return err
+ }
+ return nil
+}
+
+// CreateImage creates a disk image that is suitable for syzkaller.
+// Kernel is taken from kernelDir, userspace system is taken from userspaceDir.
+// The resulting image is marked with tag and copied to the specified image file.
+func CreateImage(kernelDir, userspaceDir, tag, image string) error {
+ tempDir, err := ioutil.TempDir("", "syz-build")
+ if err != nil {
+ return err
+ }
+ defer os.RemoveAll(tempDir)
+ scriptFile := filepath.Join(tempDir, "create.sh")
+ if err := ioutil.WriteFile(scriptFile, []byte(createImageScript), 0700); err != nil {
+ return fmt.Errorf("failed to write script file: %v", err)
+ }
+ vmlinux := filepath.Join(kernelDir, "vmlinux")
+ bzImage := filepath.Join(kernelDir, "arch/x86/boot/bzImage")
+ if _, err := osutil.RunCmd(time.Hour, tempDir, scriptFile, userspaceDir, bzImage, vmlinux, tag); err != nil {
+ return fmt.Errorf("image build failed: %v", err)
+ }
+ if err := os.Rename(filepath.Join(tempDir, "image.tar.gz"), image); err != nil {
+ return err
+ }
+ return nil
+}