1f3a0208fSAlexander Bulekov======== 2f3a0208fSAlexander BulekovFuzzing 3f3a0208fSAlexander Bulekov======== 4f3a0208fSAlexander Bulekov 5f3a0208fSAlexander BulekovThis document describes the virtual-device fuzzing infrastructure in QEMU and 6f3a0208fSAlexander Bulekovhow to use it to implement additional fuzzers. 7f3a0208fSAlexander Bulekov 8f3a0208fSAlexander BulekovBasics 9f3a0208fSAlexander Bulekov------ 10f3a0208fSAlexander Bulekov 11f3a0208fSAlexander BulekovFuzzing operates by passing inputs to an entry point/target function. The 12f3a0208fSAlexander Bulekovfuzzer tracks the code coverage triggered by the input. Based on these 13f3a0208fSAlexander Bulekovfindings, the fuzzer mutates the input and repeats the fuzzing. 14f3a0208fSAlexander Bulekov 15f3a0208fSAlexander BulekovTo fuzz QEMU, we rely on libfuzzer. Unlike other fuzzers such as AFL, libfuzzer 16f3a0208fSAlexander Bulekovis an *in-process* fuzzer. For the developer, this means that it is their 17f3a0208fSAlexander Bulekovresponsibility to ensure that state is reset between fuzzing-runs. 18f3a0208fSAlexander Bulekov 19f3a0208fSAlexander BulekovBuilding the fuzzers 20f3a0208fSAlexander Bulekov-------------------- 21f3a0208fSAlexander Bulekov 22f3a0208fSAlexander Bulekov*NOTE*: If possible, build a 32-bit binary. When forking, the 32-bit fuzzer is 23f3a0208fSAlexander Bulekovmuch faster, since the page-map has a smaller size. This is due to the fact that 24f3a0208fSAlexander BulekovAddressSanitizer maps ~20TB of memory, as part of its detection. This results 25f3a0208fSAlexander Bulekovin a large page-map, and a much slower ``fork()``. 26f3a0208fSAlexander Bulekov 27f3a0208fSAlexander BulekovTo build the fuzzers, install a recent version of clang: 28f3a0208fSAlexander BulekovConfigure with (substitute the clang binaries with the version you installed). 29f3a0208fSAlexander BulekovHere, enable-sanitizers, is optional but it allows us to reliably detect bugs 30f3a0208fSAlexander Bulekovsuch as out-of-bounds accesses, use-after-frees, double-frees etc.:: 31f3a0208fSAlexander Bulekov 32f3a0208fSAlexander Bulekov CC=clang-8 CXX=clang++-8 /path/to/configure --enable-fuzzing \ 33f3a0208fSAlexander Bulekov --enable-sanitizers 34f3a0208fSAlexander Bulekov 35f3a0208fSAlexander BulekovFuzz targets are built similarly to system targets:: 36f3a0208fSAlexander Bulekov 37e6a3e132SAlexander Bulekov make qemu-fuzz-i386 38f3a0208fSAlexander Bulekov 39e6a3e132SAlexander BulekovThis builds ``./qemu-fuzz-i386`` 40f3a0208fSAlexander Bulekov 41f3a0208fSAlexander BulekovThe first option to this command is: ``--fuzz-target=FUZZ_NAME`` 42f3a0208fSAlexander BulekovTo list all of the available fuzzers run ``qemu-fuzz-i386`` with no arguments. 43f3a0208fSAlexander Bulekov 44f3a0208fSAlexander BulekovFor example:: 45f3a0208fSAlexander Bulekov 46e6a3e132SAlexander Bulekov ./qemu-fuzz-i386 --fuzz-target=virtio-scsi-fuzz 47f3a0208fSAlexander Bulekov 48f3a0208fSAlexander BulekovInternally, libfuzzer parses all arguments that do not begin with ``"--"``. 49f3a0208fSAlexander BulekovInformation about these is available by passing ``-help=1`` 50f3a0208fSAlexander Bulekov 51f3a0208fSAlexander BulekovNow the only thing left to do is wait for the fuzzer to trigger potential 52f3a0208fSAlexander Bulekovcrashes. 53f3a0208fSAlexander Bulekov 54f3a0208fSAlexander BulekovUseful libFuzzer flags 55f3a0208fSAlexander Bulekov---------------------- 56f3a0208fSAlexander Bulekov 57f3a0208fSAlexander BulekovAs mentioned above, libFuzzer accepts some arguments. Passing ``-help=1`` will 58f3a0208fSAlexander Bulekovlist the available arguments. In particular, these arguments might be helpful: 59f3a0208fSAlexander Bulekov 60f3a0208fSAlexander Bulekov* ``CORPUS_DIR/`` : Specify a directory as the last argument to libFuzzer. 61f3a0208fSAlexander Bulekov libFuzzer stores each "interesting" input in this corpus directory. The next 62f3a0208fSAlexander Bulekov time you run libFuzzer, it will read all of the inputs from the corpus, and 63f3a0208fSAlexander Bulekov continue fuzzing from there. You can also specify multiple directories. 64f3a0208fSAlexander Bulekov libFuzzer loads existing inputs from all specified directories, but will only 65f3a0208fSAlexander Bulekov write new ones to the first one specified. 66f3a0208fSAlexander Bulekov 67f3a0208fSAlexander Bulekov* ``-max_len=4096`` : specify the maximum byte-length of the inputs libFuzzer 68f3a0208fSAlexander Bulekov will generate. 69f3a0208fSAlexander Bulekov 70f3a0208fSAlexander Bulekov* ``-close_fd_mask={1,2,3}`` : close, stderr, or both. Useful for targets that 71f3a0208fSAlexander Bulekov trigger many debug/error messages, or create output on the serial console. 72f3a0208fSAlexander Bulekov 73f3a0208fSAlexander Bulekov* ``-jobs=4 -workers=4`` : These arguments configure libFuzzer to run 4 fuzzers in 74f3a0208fSAlexander Bulekov parallel (4 fuzzing jobs in 4 worker processes). Alternatively, with only 75f3a0208fSAlexander Bulekov ``-jobs=N``, libFuzzer automatically spawns a number of workers less than or equal 76f3a0208fSAlexander Bulekov to half the available CPU cores. Replace 4 with a number appropriate for your 77f3a0208fSAlexander Bulekov machine. Make sure to specify a ``CORPUS_DIR``, which will allow the parallel 78f3a0208fSAlexander Bulekov fuzzers to share information about the interesting inputs they find. 79f3a0208fSAlexander Bulekov 80f3a0208fSAlexander Bulekov* ``-use_value_profile=1`` : For each comparison operation, libFuzzer computes 81f3a0208fSAlexander Bulekov ``(caller_pc&4095) | (popcnt(Arg1 ^ Arg2) << 12)`` and places this in the 82f3a0208fSAlexander Bulekov coverage table. Useful for targets with "magic" constants. If Arg1 came from 83f3a0208fSAlexander Bulekov the fuzzer's input and Arg2 is a magic constant, then each time the Hamming 84f3a0208fSAlexander Bulekov distance between Arg1 and Arg2 decreases, libFuzzer adds the input to the 85f3a0208fSAlexander Bulekov corpus. 86f3a0208fSAlexander Bulekov 87f3a0208fSAlexander Bulekov* ``-shrink=1`` : Tries to make elements of the corpus "smaller". Might lead to 88f3a0208fSAlexander Bulekov better coverage performance, depending on the target. 89f3a0208fSAlexander Bulekov 90f3a0208fSAlexander BulekovNote that libFuzzer's exact behavior will depend on the version of 91f3a0208fSAlexander Bulekovclang and libFuzzer used to build the device fuzzers. 92f3a0208fSAlexander Bulekov 93f3a0208fSAlexander BulekovGenerating Coverage Reports 94f3a0208fSAlexander Bulekov--------------------------- 95f3a0208fSAlexander Bulekov 96f3a0208fSAlexander BulekovCode coverage is a crucial metric for evaluating a fuzzer's performance. 97f3a0208fSAlexander BulekovlibFuzzer's output provides a "cov: " column that provides a total number of 98f3a0208fSAlexander Bulekovunique blocks/edges covered. To examine coverage on a line-by-line basis we 99f3a0208fSAlexander Bulekovcan use Clang coverage: 100f3a0208fSAlexander Bulekov 101f3a0208fSAlexander Bulekov 1. Configure libFuzzer to store a corpus of all interesting inputs (see 102f3a0208fSAlexander Bulekov CORPUS_DIR above) 103f3a0208fSAlexander Bulekov 2. ``./configure`` the QEMU build with :: 104f3a0208fSAlexander Bulekov 105f3a0208fSAlexander Bulekov --enable-fuzzing \ 106f3a0208fSAlexander Bulekov --extra-cflags="-fprofile-instr-generate -fcoverage-mapping" 107f3a0208fSAlexander Bulekov 108f3a0208fSAlexander Bulekov 3. Re-run the fuzzer. Specify $CORPUS_DIR/* as an argument, telling libfuzzer 109f3a0208fSAlexander Bulekov to execute all of the inputs in $CORPUS_DIR and exit. Once the process 110f3a0208fSAlexander Bulekov exits, you should find a file, "default.profraw" in the working directory. 111f3a0208fSAlexander Bulekov 4. Execute these commands to generate a detailed HTML coverage-report:: 112f3a0208fSAlexander Bulekov 113f3a0208fSAlexander Bulekov llvm-profdata merge -output=default.profdata default.profraw 114f3a0208fSAlexander Bulekov llvm-cov show ./path/to/qemu-fuzz-i386 -instr-profile=default.profdata \ 115f3a0208fSAlexander Bulekov --format html -output-dir=/path/to/output/report 116f3a0208fSAlexander Bulekov 117f3a0208fSAlexander BulekovAdding a new fuzzer 118f3a0208fSAlexander Bulekov------------------- 119f3a0208fSAlexander Bulekov 120f3a0208fSAlexander BulekovCoverage over virtual devices can be improved by adding additional fuzzers. 121f3a0208fSAlexander BulekovFuzzers are kept in ``tests/qtest/fuzz/`` and should be added to 12292381157SAlexander Bulekov``tests/qtest/fuzz/meson.build`` 123f3a0208fSAlexander Bulekov 124f3a0208fSAlexander BulekovFuzzers can rely on both qtest and libqos to communicate with virtual devices. 125f3a0208fSAlexander Bulekov 126f3a0208fSAlexander Bulekov1. Create a new source file. For example ``tests/qtest/fuzz/foo-device-fuzz.c``. 127f3a0208fSAlexander Bulekov 128f3a0208fSAlexander Bulekov2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers 129f3a0208fSAlexander Bulekov for reference. 130f3a0208fSAlexander Bulekov 13192381157SAlexander Bulekov3. Add the fuzzer to ``tests/qtest/fuzz/meson.build``. 132f3a0208fSAlexander Bulekov 133f3a0208fSAlexander BulekovFuzzers can be more-or-less thought of as special qtest programs which can 134f3a0208fSAlexander Bulekovmodify the qtest commands and/or qtest command arguments based on inputs 135f3a0208fSAlexander Bulekovprovided by libfuzzer. Libfuzzer passes a byte array and length. Commonly the 136f3a0208fSAlexander Bulekovfuzzer loops over the byte-array interpreting it as a list of qtest commands, 137f3a0208fSAlexander Bulekovaddresses, or values. 138f3a0208fSAlexander Bulekov 139f3a0208fSAlexander BulekovThe Generic Fuzzer 140f3a0208fSAlexander Bulekov------------------ 141f3a0208fSAlexander Bulekov 142f3a0208fSAlexander BulekovWriting a fuzz target can be a lot of effort (especially if a device driver has 143f3a0208fSAlexander Bulekovnot be built-out within libqos). Many devices can be fuzzed to some degree, 144f3a0208fSAlexander Bulekovwithout any device-specific code, using the generic-fuzz target. 145f3a0208fSAlexander Bulekov 146f3a0208fSAlexander BulekovThe generic-fuzz target is capable of fuzzing devices over their PIO, MMIO, 147f3a0208fSAlexander Bulekovand DMA input-spaces. To apply the generic-fuzz to a device, we need to define 148f3a0208fSAlexander Bulekovtwo env-variables, at minimum: 149f3a0208fSAlexander Bulekov 150f3a0208fSAlexander Bulekov* ``QEMU_FUZZ_ARGS=`` is the set of QEMU arguments used to configure a machine, with 151f3a0208fSAlexander Bulekov the device attached. For example, if we want to fuzz the virtio-net device 152f3a0208fSAlexander Bulekov attached to a pc-i440fx machine, we can specify:: 153f3a0208fSAlexander Bulekov 154f3a0208fSAlexander Bulekov QEMU_FUZZ_ARGS="-M pc -nodefaults -netdev user,id=user0 \ 155f3a0208fSAlexander Bulekov -device virtio-net,netdev=user0" 156f3a0208fSAlexander Bulekov 157f3a0208fSAlexander Bulekov* ``QEMU_FUZZ_OBJECTS=`` is a set of space-delimited strings used to identify 158f3a0208fSAlexander Bulekov the MemoryRegions that will be fuzzed. These strings are compared against 159f3a0208fSAlexander Bulekov MemoryRegion names and MemoryRegion owner names, to decide whether each 160f3a0208fSAlexander Bulekov MemoryRegion should be fuzzed. These strings support globbing. For the 161f3a0208fSAlexander Bulekov virtio-net example, we could use one of :: 162f3a0208fSAlexander Bulekov 163f3a0208fSAlexander Bulekov QEMU_FUZZ_OBJECTS='virtio-net' 164f3a0208fSAlexander Bulekov QEMU_FUZZ_OBJECTS='virtio*' 165f3a0208fSAlexander Bulekov QEMU_FUZZ_OBJECTS='virtio* pcspk' # Fuzz the virtio devices and the speaker 166f3a0208fSAlexander Bulekov QEMU_FUZZ_OBJECTS='*' # Fuzz the whole machine`` 167f3a0208fSAlexander Bulekov 168f3a0208fSAlexander BulekovThe ``"info mtree"`` and ``"info qom-tree"`` monitor commands can be especially 169f3a0208fSAlexander Bulekovuseful for identifying the ``MemoryRegion`` and ``Object`` names used for 170f3a0208fSAlexander Bulekovmatching. 171f3a0208fSAlexander Bulekov 172f3a0208fSAlexander BulekovAs a generic rule-of-thumb, the more ``MemoryRegions``/Devices we match, the 173f3a0208fSAlexander Bulekovgreater the input-space, and the smaller the probability of finding crashing 174f3a0208fSAlexander Bulekovinputs for individual devices. As such, it is usually a good idea to limit the 175f3a0208fSAlexander Bulekovfuzzer to only a few ``MemoryRegions``. 176f3a0208fSAlexander Bulekov 177f3a0208fSAlexander BulekovTo ensure that these env variables have been configured correctly, we can use:: 178f3a0208fSAlexander Bulekov 179f3a0208fSAlexander Bulekov ./qemu-fuzz-i386 --fuzz-target=generic-fuzz -runs=0 180f3a0208fSAlexander Bulekov 181f3a0208fSAlexander BulekovThe output should contain a complete list of matched MemoryRegions. 182f3a0208fSAlexander Bulekov 1833ca45fb4SAlexander BulekovOSS-Fuzz 1843ca45fb4SAlexander Bulekov-------- 185450e0f28SJohn SnowQEMU is continuously fuzzed on `OSS-Fuzz 186450e0f28SJohn Snow<https://github.com/google/oss-fuzz>`_. By default, the OSS-Fuzz build 187450e0f28SJohn Snowwill try to fuzz every fuzz-target. Since the generic-fuzz target 188450e0f28SJohn Snowrequires additional information provided in environment variables, we 189450e0f28SJohn Snowpre-define some generic-fuzz configs in 1903ca45fb4SAlexander Bulekov``tests/qtest/fuzz/generic_fuzz_configs.h``. Each config must specify: 1913ca45fb4SAlexander Bulekov 1923ca45fb4SAlexander Bulekov- ``.name``: To identify the fuzzer config 1933ca45fb4SAlexander Bulekov 1943ca45fb4SAlexander Bulekov- ``.args`` OR ``.argfunc``: A string or pointer to a function returning a 1953ca45fb4SAlexander Bulekov string. These strings are used to specify the ``QEMU_FUZZ_ARGS`` 1963ca45fb4SAlexander Bulekov environment variable. ``argfunc`` is useful when the config relies on e.g. 1973ca45fb4SAlexander Bulekov a dynamically created temp directory, or a free tcp/udp port. 1983ca45fb4SAlexander Bulekov 1993ca45fb4SAlexander Bulekov- ``.objects``: A string that specifies the ``QEMU_FUZZ_OBJECTS`` environment 2003ca45fb4SAlexander Bulekov variable. 2013ca45fb4SAlexander Bulekov 2023ca45fb4SAlexander BulekovTo fuzz additional devices/device configuration on OSS-Fuzz, send patches for 2033ca45fb4SAlexander Bulekoveither a new device-specific fuzzer or a new generic-fuzz config. 2043ca45fb4SAlexander Bulekov 2053ca45fb4SAlexander BulekovBuild details: 2063ca45fb4SAlexander Bulekov 2073ca45fb4SAlexander Bulekov- The Dockerfile that sets up the environment for building QEMU's 2083ca45fb4SAlexander Bulekov fuzzers on OSS-Fuzz can be fund in the OSS-Fuzz repository 2093ca45fb4SAlexander Bulekov __(https://github.com/google/oss-fuzz/blob/master/projects/qemu/Dockerfile) 2103ca45fb4SAlexander Bulekov 2113ca45fb4SAlexander Bulekov- The script responsible for building the fuzzers can be found in the 2123ca45fb4SAlexander Bulekov QEMU source tree at ``scripts/oss-fuzz/build.sh`` 2133ca45fb4SAlexander Bulekov 21456f8f888SAlexander BulekovBuilding Crash Reproducers 21556f8f888SAlexander Bulekov----------------------------------------- 21656f8f888SAlexander BulekovWhen we find a crash, we should try to create an independent reproducer, that 21756f8f888SAlexander Bulekovcan be used on a non-fuzzer build of QEMU. This filters out any potential 21856f8f888SAlexander Bulekovfalse-positives, and improves the debugging experience for developers. 21956f8f888SAlexander BulekovHere are the steps for building a reproducer for a crash found by the 22056f8f888SAlexander Bulekovgeneric-fuzz target. 22156f8f888SAlexander Bulekov 22256f8f888SAlexander Bulekov- Ensure the crash reproduces:: 22356f8f888SAlexander Bulekov 22456f8f888SAlexander Bulekov qemu-fuzz-i386 --fuzz-target... ./crash-... 22556f8f888SAlexander Bulekov 22656f8f888SAlexander Bulekov- Gather the QTest output for the crash:: 22756f8f888SAlexander Bulekov 22856f8f888SAlexander Bulekov QEMU_FUZZ_TIMEOUT=0 QTEST_LOG=1 FUZZ_SERIALIZE_QTEST=1 \ 22956f8f888SAlexander Bulekov qemu-fuzz-i386 --fuzz-target... ./crash-... &> /tmp/trace 23056f8f888SAlexander Bulekov 23156f8f888SAlexander Bulekov- Reorder and clean-up the resulting trace:: 23256f8f888SAlexander Bulekov 23356f8f888SAlexander Bulekov scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py /tmp/trace > /tmp/reproducer 23456f8f888SAlexander Bulekov 23556f8f888SAlexander Bulekov- Get the arguments needed to start qemu, and provide a path to qemu:: 23656f8f888SAlexander Bulekov 23756f8f888SAlexander Bulekov less /tmp/trace # The args should be logged at the top of this file 23856f8f888SAlexander Bulekov export QEMU_ARGS="-machine ..." 23956f8f888SAlexander Bulekov export QEMU_PATH="path/to/qemu-system" 24056f8f888SAlexander Bulekov 24156f8f888SAlexander Bulekov- Ensure the crash reproduces in qemu-system:: 24256f8f888SAlexander Bulekov 24356f8f888SAlexander Bulekov $QEMU_PATH $QEMU_ARGS -qtest stdio < /tmp/reproducer 24456f8f888SAlexander Bulekov 24556f8f888SAlexander Bulekov- From the crash output, obtain some string that identifies the crash. This 24656f8f888SAlexander Bulekov can be a line in the stack-trace, for example:: 24756f8f888SAlexander Bulekov 24856f8f888SAlexander Bulekov export CRASH_TOKEN="hw/usb/hcd-xhci.c:1865" 24956f8f888SAlexander Bulekov 25056f8f888SAlexander Bulekov- Minimize the reproducer:: 25156f8f888SAlexander Bulekov 25256f8f888SAlexander Bulekov scripts/oss-fuzz/minimize_qtest_trace.py -M1 -M2 \ 25356f8f888SAlexander Bulekov /tmp/reproducer /tmp/reproducer-minimized 25456f8f888SAlexander Bulekov 25556f8f888SAlexander Bulekov- Confirm that the minimized reproducer still crashes:: 25656f8f888SAlexander Bulekov 25756f8f888SAlexander Bulekov $QEMU_PATH $QEMU_ARGS -qtest stdio < /tmp/reproducer-minimized 25856f8f888SAlexander Bulekov 25956f8f888SAlexander Bulekov- Create a one-liner reproducer that can be sent over email:: 26056f8f888SAlexander Bulekov 26156f8f888SAlexander Bulekov ./scripts/oss-fuzz/output_reproducer.py -bash /tmp/reproducer-minimized 26256f8f888SAlexander Bulekov 26356f8f888SAlexander Bulekov- Output the C source code for a test case that will reproduce the bug:: 26456f8f888SAlexander Bulekov 26556f8f888SAlexander Bulekov ./scripts/oss-fuzz/output_reproducer.py -owner "John Smith <john@smith.com>"\ 26656f8f888SAlexander Bulekov -name "test_function_name" /tmp/reproducer-minimized 26756f8f888SAlexander Bulekov 26856f8f888SAlexander Bulekov- Report the bug and send a patch with the C reproducer upstream 26956f8f888SAlexander Bulekov 270f3a0208fSAlexander BulekovImplementation Details / Fuzzer Lifecycle 271f3a0208fSAlexander Bulekov----------------------------------------- 272f3a0208fSAlexander Bulekov 273f3a0208fSAlexander BulekovThe fuzzer has two entrypoints that libfuzzer calls. libfuzzer provides it's 274f3a0208fSAlexander Bulekovown ``main()``, which performs some setup, and calls the entrypoints: 275f3a0208fSAlexander Bulekov 276f3a0208fSAlexander Bulekov``LLVMFuzzerInitialize``: called prior to fuzzing. Used to initialize all of the 277f3a0208fSAlexander Bulekovnecessary state 278f3a0208fSAlexander Bulekov 279f3a0208fSAlexander Bulekov``LLVMFuzzerTestOneInput``: called for each fuzzing run. Processes the input and 280f3a0208fSAlexander Bulekovresets the state at the end of each run. 281f3a0208fSAlexander Bulekov 282f3a0208fSAlexander BulekovIn more detail: 283f3a0208fSAlexander Bulekov 284f3a0208fSAlexander Bulekov``LLVMFuzzerInitialize`` parses the arguments to the fuzzer (must start with two 285f3a0208fSAlexander Bulekovdashes, so they are ignored by libfuzzer ``main()``). Currently, the arguments 286f3a0208fSAlexander Bulekovselect the fuzz target. Then, the qtest client is initialized. If the target 287f3a0208fSAlexander Bulekovrequires qos, qgraph is set up and the QOM/LIBQOS modules are initialized. 288f3a0208fSAlexander BulekovThen the QGraph is walked and the QEMU cmd_line is determined and saved. 289f3a0208fSAlexander Bulekov 290*bab6a301SAkihiko OdakiAfter this, the ``vl.c:main`` is called to set up the guest. There are 291*bab6a301SAkihiko Odakitarget-specific hooks that can be called before and after main, for 292f3a0208fSAlexander Bulekovadditional setup(e.g. PCI setup, or VM snapshotting). 293f3a0208fSAlexander Bulekov 294f3a0208fSAlexander Bulekov``LLVMFuzzerTestOneInput``: Uses qtest/qos functions to act based on the fuzz 295f3a0208fSAlexander Bulekovinput. It is also responsible for manually calling ``main_loop_wait`` to ensure 296f3a0208fSAlexander Bulekovthat bottom halves are executed and any cleanup required before the next input. 297f3a0208fSAlexander Bulekov 298f3a0208fSAlexander BulekovSince the same process is reused for many fuzzing runs, QEMU state needs to 299f3a0208fSAlexander Bulekovbe reset at the end of each run. There are currently two implemented 300f3a0208fSAlexander Bulekovoptions for resetting state: 301f3a0208fSAlexander Bulekov 302f3a0208fSAlexander Bulekov- Reboot the guest between runs. 303f3a0208fSAlexander Bulekov - *Pros*: Straightforward and fast for simple fuzz targets. 304f3a0208fSAlexander Bulekov 305f3a0208fSAlexander Bulekov - *Cons*: Depending on the device, does not reset all device state. If the 306f3a0208fSAlexander Bulekov device requires some initialization prior to being ready for fuzzing (common 307f3a0208fSAlexander Bulekov for QOS-based targets), this initialization needs to be done after each 308f3a0208fSAlexander Bulekov reboot. 309f3a0208fSAlexander Bulekov 310f3a0208fSAlexander Bulekov - *Example target*: ``i440fx-qtest-reboot-fuzz`` 311f3a0208fSAlexander Bulekov 312f3a0208fSAlexander Bulekov- Run each test case in a separate forked process and copy the coverage 313f3a0208fSAlexander Bulekov information back to the parent. This is fairly similar to AFL's "deferred" 314f3a0208fSAlexander Bulekov fork-server mode [3] 315f3a0208fSAlexander Bulekov 316f3a0208fSAlexander Bulekov - *Pros*: Relatively fast. Devices only need to be initialized once. No need to 317f3a0208fSAlexander Bulekov do slow reboots or vmloads. 318f3a0208fSAlexander Bulekov 319f3a0208fSAlexander Bulekov - *Cons*: Not officially supported by libfuzzer. Does not work well for 320f3a0208fSAlexander Bulekov devices that rely on dedicated threads. 321f3a0208fSAlexander Bulekov 322f3a0208fSAlexander Bulekov - *Example target*: ``virtio-net-fork-fuzz`` 323