1# 2# SPDX-License-Identifier: MIT 3# 4 5from oeqa.selftest.case import OESelftestTestCase 6from oeqa.utils.commands import runCmd, bitbake, get_bb_var, get_bb_vars 7from oeqa.utils.network import get_free_port 8 9class TestSyzkaller(OESelftestTestCase): 10 def setUpSyzkallerConfig(self, os_arch, qemu_postfix): 11 syz_target_sysroot = get_bb_var('PKGD', 'syzkaller') 12 syz_target = os.path.join(syz_target_sysroot, 'usr') 13 14 qemu_native_bin = os.path.join(self.syz_native_sysroot, 'usr/bin/qemu-system-' + qemu_postfix) 15 kernel_cmdline = "ip=dhcp rootfs=/dev/sda dummy_hcd.num=%s" % (self.dummy_hcd_num) 16 kernel_objdir = self.deploy_dir_image 17 port = get_free_port() 18 19 if not os.path.exists(self.syz_workdir): 20 os.mkdir(self.syz_workdir) 21 22 with open(self.syz_cfg, 'w') as f: 23 f.write( 24""" 25{ 26 "target": "%s", 27 "http": "127.0.0.1:%s", 28 "workdir": "%s", 29 "kernel_obj": "%s", 30 "kernel_src": "%s", 31 "image": "%s", 32 "syzkaller": "%s", 33 "type": "qemu", 34 "reproduce" : false, 35 "sandbox": "none", 36 "vm": { 37 "count": %s, 38 "kernel": "%s", 39 "cmdline": "%s", 40 "cpu": %s, 41 "mem": %s, 42 "qemu": "%s", 43 "qemu_args": "-device virtio-scsi-pci,id=scsi -device scsi-hd,drive=rootfs -enable-kvm -cpu host,migratable=off", 44 "image_device": "drive index=0,id=rootfs,if=none,media=disk,file=" 45 } 46} 47""" 48% (os_arch, port, self.syz_workdir, kernel_objdir, self.kernel_src, 49 self.rootfs, syz_target, self.syz_qemu_vms, self.kernel, kernel_cmdline, 50 self.syz_qemu_cpus, self.syz_qemu_mem, qemu_native_bin)) 51 52 def test_syzkallerFuzzingQemux86_64(self): 53 self.image = 'core-image-minimal' 54 self.machine = 'qemux86-64' 55 self.fstype = "ext4" 56 57 self.write_config( 58""" 59MACHINE = "%s" 60IMAGE_FSTYPES = "%s" 61KERNEL_IMAGETYPES += "vmlinux" 62EXTRA_IMAGE_FEATURES += " ssh-server-openssh" 63IMAGE_ROOTFS_EXTRA_SPACE = "512000" 64KERNEL_EXTRA_FEATURES += " \ 65 cfg/debug/syzkaller/debug-syzkaller.scc \ 66" 67IMAGE_INSTALL:append = " syzkaller" 68""" 69% (self.machine, self.fstype)) 70 71 build_vars = ['TOPDIR', 'DEPLOY_DIR_IMAGE', 'STAGING_KERNEL_DIR'] 72 syz_fuzz_vars = ['SYZ_WORKDIR', 'SYZ_FUZZTIME', 'SYZ_QEMU_MEM', 'SYZ_QEMU_CPUS', 'SYZ_QEMU_VM_COUNT'] 73 syz_aux_vars = ['SYZ_DUMMY_HCD_NUM'] 74 75 needed_vars = build_vars + syz_fuzz_vars + syz_aux_vars 76 bb_vars = get_bb_vars(needed_vars) 77 78 for var in syz_fuzz_vars: 79 if not bb_vars[var]: 80 self.skipTest( 81""" 82%s variable not set. 83Please configure %s fuzzing parameters to run this test. 84 85Example local.conf config: 86SYZ_WORKDIR="<path>" # syzkaller workdir location (must be persistent across os-selftest runs) 87SYZ_FUZZTIME="30" # fuzzing time in minutes 88SYZ_QEMU_VM_COUNT="1" # number of qemu VMs to be used for fuzzing 89SYZ_QEMU_MEM="2048"' # memory used by each qemu VM 90SYZ_QEMU_CPUS="2"' # number of cpus used by each qemu VM 91""" 92% (var, ', '.join(syz_fuzz_vars))) 93 94 self.topdir = bb_vars['TOPDIR'] 95 self.deploy_dir_image = bb_vars['DEPLOY_DIR_IMAGE'] 96 self.kernel_src = bb_vars['STAGING_KERNEL_DIR'] 97 98 """ 99 SYZ_WORKDIR must be set to an absolute path where syzkaller will store 100 the corpus database, config, runtime and crash data generated during 101 fuzzing. It must be persistent between oe-selftest runs, so the fuzzer 102 does not start over again on each run. 103 """ 104 self.syz_workdir = bb_vars['SYZ_WORKDIR'] 105 self.syz_fuzztime = int(bb_vars['SYZ_FUZZTIME']) * 60 106 self.syz_qemu_mem = int(bb_vars['SYZ_QEMU_MEM']) 107 self.syz_qemu_cpus = int(bb_vars['SYZ_QEMU_CPUS']) 108 self.syz_qemu_vms = int(bb_vars['SYZ_QEMU_VM_COUNT']) 109 self.dummy_hcd_num = int(bb_vars['SYZ_DUMMY_HCD_NUM'] or 8) 110 111 self.syz_cfg = os.path.join(self.syz_workdir, 'syzkaller.cfg') 112 self.kernel = os.path.join(self.deploy_dir_image, 'bzImage') 113 self.rootfs = os.path.join(self.deploy_dir_image, '%s-%s.%s' % (self.image, self.machine, self.fstype)) 114 115 self.syz_native_sysroot = get_bb_var('RECIPE_SYSROOT_NATIVE', 'syzkaller-native') 116 117 self.setUpSyzkallerConfig("linux/amd64", "x86_64") 118 119 bitbake(self.image) 120 bitbake('syzkaller') 121 bitbake('syzkaller-native -c addto_recipe_sysroot') 122 123 cmd = "syz-manager -config %s" % self.syz_cfg 124 runCmd(cmd, native_sysroot = self.syz_native_sysroot, timeout=self.syz_fuzztime, output_log=self.logger, ignore_status=True, shell=True) 125