syzkaller.py 4.4 KB

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