|
@@ -0,0 +1,124 @@
|
|
|
|
+#
|
|
|
|
+# SPDX-License-Identifier: MIT
|
|
|
|
+#
|
|
|
|
+
|
|
|
|
+from oeqa.selftest.case import OESelftestTestCase
|
|
|
|
+from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars
|
|
|
|
+from oeqa.utils.network import get_free_port
|
|
|
|
+
|
|
|
|
+class TestSyzkaller(OESelftestTestCase):
|
|
|
|
+ def setUpSyzkallerConfig(self, os_arch, qemu_postfix):
|
|
|
|
+ syz_target_sysroot = get_bb_var('PKGD', 'syzkaller')
|
|
|
|
+ syz_target = os.path.join(syz_target_sysroot, 'usr')
|
|
|
|
+
|
|
|
|
+ qemu_native_bin = os.path.join(self.syz_native_sysroot, 'usr/bin/qemu-system-' + qemu_postfix)
|
|
|
|
+ kernel_cmdline = "ip=dhcp rootfs=/dev/sda dummy_hcd.num=%s" % (self.dummy_hcd_num)
|
|
|
|
+ kernel_objdir = self.deploy_dir_image
|
|
|
|
+ port = get_free_port()
|
|
|
|
+
|
|
|
|
+ if not os.path.exists(self.syz_workdir):
|
|
|
|
+ os.mkdir(self.syz_workdir)
|
|
|
|
+
|
|
|
|
+ with open(self.syz_cfg, 'w') as f:
|
|
|
|
+ f.write(
|
|
|
|
+"""
|
|
|
|
+{
|
|
|
|
+ "target": "%s",
|
|
|
|
+ "http": "127.0.0.1:%s",
|
|
|
|
+ "workdir": "%s",
|
|
|
|
+ "kernel_obj": "%s",
|
|
|
|
+ "kernel_src": "%s",
|
|
|
|
+ "image": "%s",
|
|
|
|
+ "syzkaller": "%s",
|
|
|
|
+ "type": "qemu",
|
|
|
|
+ "reproduce" : false,
|
|
|
|
+ "sandbox": "none",
|
|
|
|
+ "vm": {
|
|
|
|
+ "count": %s,
|
|
|
|
+ "kernel": "%s",
|
|
|
|
+ "cmdline": "%s",
|
|
|
|
+ "cpu": %s,
|
|
|
|
+ "mem": %s,
|
|
|
|
+ "qemu": "%s",
|
|
|
|
+ "qemu_args": "-device virtio-scsi-pci,id=scsi -device scsi-hd,drive=rootfs -enable-kvm -cpu host,migratable=off",
|
|
|
|
+ "image_device": "drive index=0,id=rootfs,if=none,media=disk,file="
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+"""
|
|
|
|
+% (os_arch, port, self.syz_workdir, kernel_objdir, self.kernel_src,
|
|
|
|
+ self.rootfs, syz_target, self.syz_qemu_vms, self.kernel, kernel_cmdline,
|
|
|
|
+ self.syz_qemu_cpus, self.syz_qemu_mem, qemu_native_bin))
|
|
|
|
+
|
|
|
|
+ def test_syzkallerFuzzingQemux86_64(self):
|
|
|
|
+ self.image = 'core-image-minimal'
|
|
|
|
+ self.machine = 'qemux86-64'
|
|
|
|
+ self.fstype = "ext4"
|
|
|
|
+
|
|
|
|
+ self.write_config(
|
|
|
|
+"""
|
|
|
|
+MACHINE = "%s"
|
|
|
|
+IMAGE_FSTYPES = "%s"
|
|
|
|
+KERNEL_IMAGETYPES += "vmlinux"
|
|
|
|
+EXTRA_IMAGE_FEATURES += " ssh-server-openssh"
|
|
|
|
+IMAGE_ROOTFS_EXTRA_SPACE = "512000"
|
|
|
|
+KERNEL_EXTRA_FEATURES += " \
|
|
|
|
+ cfg/debug/syzkaller/debug-syzkaller.scc \
|
|
|
|
+"
|
|
|
|
+IMAGE_INSTALL:append = " syzkaller"
|
|
|
|
+"""
|
|
|
|
+% (self.machine, self.fstype))
|
|
|
|
+
|
|
|
|
+ build_vars = ['TOPDIR', 'DEPLOY_DIR_IMAGE', 'STAGING_KERNEL_DIR']
|
|
|
|
+ syz_fuzz_vars = ['SYZ_WORKDIR', 'SYZ_FUZZTIME', 'SYZ_QEMU_MEM', 'SYZ_QEMU_CPUS', 'SYZ_QEMU_VM_COUNT']
|
|
|
|
+ syz_aux_vars = ['SYZ_DUMMY_HCD_NUM']
|
|
|
|
+
|
|
|
|
+ needed_vars = build_vars + syz_fuzz_vars + syz_aux_vars
|
|
|
|
+ bb_vars = get_bb_vars(needed_vars)
|
|
|
|
+
|
|
|
|
+ for var in syz_fuzz_vars:
|
|
|
|
+ if not bb_vars[var]:
|
|
|
|
+ self.skipTest(
|
|
|
|
+"""
|
|
|
|
+%s variable not set.
|
|
|
|
+Please configure %s fuzzing parameters to run this test.
|
|
|
|
+
|
|
|
|
+Example local.conf config:
|
|
|
|
+SYZ_WORKDIR="<path>" # syzkaller workdir location (must be persistent across os-selftest runs)
|
|
|
|
+SYZ_FUZZTIME="30" # fuzzing time in minutes
|
|
|
|
+SYZ_QEMU_VM_COUNT="1" # number of qemu VMs to be used for fuzzing
|
|
|
|
+SYZ_QEMU_MEM="2048"' # memory used by each qemu VM
|
|
|
|
+SYZ_QEMU_CPUS="2"' # number of cpus used by each qemu VM
|
|
|
|
+"""
|
|
|
|
+% (var, ', '.join(syz_fuzz_vars)))
|
|
|
|
+
|
|
|
|
+ self.topdir = bb_vars['TOPDIR']
|
|
|
|
+ self.deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE']
|
|
|
|
+ self.kernel_src = bb_vars['STAGING_KERNEL_DIR']
|
|
|
|
+
|
|
|
|
+ """
|
|
|
|
+ SYZ_WORKDIR must be set to an absolute path where syzkaller will store
|
|
|
|
+ the corpus database, config, runtime and crash data generated during
|
|
|
|
+ fuzzing. It must be persistent between oe-selftest runs, so the fuzzer
|
|
|
|
+ does not start over again on each run.
|
|
|
|
+ """
|
|
|
|
+ self.syz_workdir = bb_vars['SYZ_WORKDIR']
|
|
|
|
+ self.syz_fuzztime = int(bb_vars['SYZ_FUZZTIME']) * 60
|
|
|
|
+ self.syz_qemu_mem = int(bb_vars['SYZ_QEMU_MEM'])
|
|
|
|
+ self.syz_qemu_cpus = int(bb_vars['SYZ_QEMU_CPUS'])
|
|
|
|
+ self.syz_qemu_vms = int(bb_vars['SYZ_QEMU_VM_COUNT'])
|
|
|
|
+ self.dummy_hcd_num = int(bb_vars['SYZ_DUMMY_HCD_NUM'] or 8)
|
|
|
|
+
|
|
|
|
+ self.syz_cfg = os.path.join(self.syz_workdir, 'syzkaller.cfg')
|
|
|
|
+ self.kernel = os.path.join(self.deploy_dir_image, 'bzImage')
|
|
|
|
+ self.rootfs = os.path.join(self.deploy_dir_image, '%s-%s.%s' % (self.image, self.machine, self.fstype))
|
|
|
|
+
|
|
|
|
+ self.syz_native_sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'syzkaller-native')
|
|
|
|
+
|
|
|
|
+ self.setUpSyzkallerConfig("linux/amd64", "x86_64")
|
|
|
|
+
|
|
|
|
+ bitbake(self.image)
|
|
|
|
+ bitbake('syzkaller')
|
|
|
|
+ bitbake('syzkaller-native -c addto_recipe_sysroot')
|
|
|
|
+
|
|
|
|
+ cmd = "syz-manager -config %s" % self.syz_cfg
|
|
|
|
+ runCmd(cmd, native_sysroot = self.syz_native_sysroot, timeout=self.syz_fuzztime, output_log=self.logger, ignore_status=True, shell=True)
|