From 34923a4e49a7dad7e4c1863dc9bd0274ab47dd41 Mon Sep 17 00:00:00 2001 From: Satheesh Rajendran Date: Tue, 19 Mar 2019 08:05:01 +0530 Subject: [PATCH] Add syzkaller testcase This adds a syzkaller fuzzing testcase for powerpc and it does the below steps 1. Install/Setup syzkaller in host 2. Setup Guest for passwordless ssh from host 3. Prepare and compile Guest kernel 4. Prepare syzkaller config with qemu params and guest params 5. Start sykaller with above config and run for specified time(test_timeout) 6. Test fails out incase of any host issues More details about syzkaller can be found here https://github.com/google/syzkaller Signed-off-by: Satheesh Rajendran --- generic/tests/cfg/syzkaller.cfg | 20 +++++++ generic/tests/syzkaller.py | 102 ++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 generic/tests/cfg/syzkaller.cfg create mode 100644 generic/tests/syzkaller.py diff --git a/generic/tests/cfg/syzkaller.cfg b/generic/tests/cfg/syzkaller.cfg new file mode 100644 index 00000000000..f644c864210 --- /dev/null +++ b/generic/tests/cfg/syzkaller.cfg @@ -0,0 +1,20 @@ +- syzkaller: + virt_test_type = qemu libvirt + type = syzkaller + # Test runs till the test timeout, make sure to adjust below param + test_timeout = 2000 + variants: + - power: + only pseries + verify_guest_dmesg = no + verify_host_dmesg = yes + kernel_args = "root=/dev/sda2 rw console=tty0 console=ttyS0,115200 init=/sbin/init initcall_debug selinux=0" + syz_qemu_args = "-enable-kvm -M pseries -net nic,model=virtio" + syz_kernel_repo = "https://github.com/linuxppc/linux.git" + syz_kernel_branch = "merge" + syz_kernel_config = "ppc64le_guest_defconfig" + syz_target = "linux/ppc64le" + syz_cmd_params = "-debug -v 10" + syz_http = "0.0.0.0:56741" + syz_count = 1 + syz_procs = 4 diff --git a/generic/tests/syzkaller.py b/generic/tests/syzkaller.py new file mode 100644 index 00000000000..847a78ca291 --- /dev/null +++ b/generic/tests/syzkaller.py @@ -0,0 +1,102 @@ +import os +import json +import time +import shutil + +from avocado.utils import software_manager +from avocado.utils import process + +from virttest import utils_misc +from virttest import ssh_key +from virttest import storage +from virttest import data_dir + + +def run(test, params, env): + """ + Setup and run syzkaller (https://github.com/google/syzkaller) + 1. Install/Setup syzkaller in host + 2. Setup Guest for passwordless ssh from host + 3. Prepare and compile Guest kernel + 4. Prepare syzkaller config with qemu params and guest params + 5. Start sykaller with above config and run for specified time(test_timeout) + 6. Test fails out incase of any host issues + """ + start_time = time.time() + # Step 1: Install/Setup syzkaller in host + sm = software_manager.SoftwareManager() + if not sm.check_installed("go") and not sm.install("go"): + test.cancel("golang package install failed") + home = os.environ["HOME"] + if not ("goroot/bin" in os.environ["PATH"] and "go/bin" in os.environ["PATH"]): + process.run('echo "PATH=%s/goroot/bin:%s/go/bin:$PATH" >> %s/.bashrc' % (home, home, home), shell=True) + process.run("source %s/.bashrc" % home, shell=True) + process.run("go get -u -d github.com/google/syzkaller/...", shell=True) + process.run("cd %s/go/src/github.com/google/syzkaller;make" % home, shell=True) + syzkaller_path = "%s/go/src/github.com/google/syzkaller" % home + + # Step 2: Setup Guest for passwordless ssh from host + vm = env.get_vm(params["main_vm"]) + session = vm.wait_for_login() + ssh_key.setup_ssh_key(vm.get_address(), + params.get("username"), + params.get("password")) + session.close() + vm.destroy() + + # Step 3: Prepare Guest kernel + guest_kernel_repo = params.get("syz_kernel_repo") + guest_kernel_branch = params.get("syz_kernel_branch") + guest_kernel_config = params.get("syz_kernel_config") + guest_kernel_build_path = utils_misc.get_path(test.debugdir, "linux") + process.run("git clone --depth 1 %s -b %s %s" % (guest_kernel_repo, guest_kernel_branch, guest_kernel_build_path), shell=True) + process.run("cd %s;git log -1;make %s" % (guest_kernel_build_path, guest_kernel_config), shell=True) + process.run('cd %s; echo "CONFIG_KCOV=y\nCONFIG_GCC_PLUGINS=y" >> .config; make olddefconfig' % guest_kernel_build_path, shell=True) + process.run("cd %s;make -j 40" % guest_kernel_build_path, shell=True) + + # Step 4: Prepare syzkaller config with qemu params and guest params + syz_config_path = utils_misc.get_path(test.debugdir, "syzkaller_config") + os.makedirs("%s/syzkaller" % test.debugdir) + fp = open(syz_config_path, "w") + workdir = "%s/syzkaller" % test.debugdir + sshkey = "%s/.ssh/id_rsa" % os.environ["HOME"] + kernel_path = "%s/vmlinux" % guest_kernel_build_path + + vm_config = { + "count": int(params.get("syz_count")), + "cpu": int(params.get("smp")), + "mem": int(params.get("mem")), + "kernel": kernel_path, + "cmdline": params.get("kernel_args"), + "qemu_args": params.get("syz_qemu_args") + } + + syz_config = { + 'target': params.get("syz_target"), + 'workdir': workdir, + "http": params.get("syz_http"), + "image": storage.get_image_filename(params, data_dir.get_data_dir()), + "syzkaller": syzkaller_path, + "procs": int(params.get("syz_procs")), + "type": "qemu", + "sshkey": sshkey, + "vm": vm_config + } + + json.dump(syz_config, fp) + fp.close() + + end_time = time.time() + # Step 5: Start sykaller config with specified time + # Let's calculate the syzkaller timeout from + # test timeout excluding current elapsed time + buffer + testtimeout = int(params.get("test_timeout")) - (int(end_time - start_time) + 10) + cmd = "%s/bin/syz-manager -config %s %s" % (syzkaller_path, syz_config_path, params.get("syz_cmd_params")) + process.run(cmd, timeout=testtimeout, + allow_output_check="combined", + ignore_status=True, shell=True) + # Let's delete linux kernel folder from test-results as it would + # consume lot of space and test log have all the information about + # it incase to retrieve it back. + if os.path.isdir(guest_kernel_build_path): + shutil.rmtree(guest_kernel_build_path)