mbox series

[v5,00/16] Add a Generic Virtual Device Fuzzer

Message ID 20201021010752.973230-1-alxndr@bu.edu
Headers show
Series Add a Generic Virtual Device Fuzzer | expand

Message

Alexander Bulekov Oct. 21, 2020, 1:07 a.m. UTC
v5:
    - Replace GArray-based predefined fuzzer configs with a static
      struct array
    - "General" -> "Generic"
    - Fix bugs with wrong timeout denominator and skipping DMA memwrites
      without QTEST_LOG
v4:
    - Replace yaml + c template-based oss-fuzz configs, with C code to
      register a FuzzTarget for each config (as suggested by Paolo)
    - Replicate the functionality of address_space_write_rom to ensure
      matching behavior when QTEST_LOG is enabled
    - Improve code documentation/comments
    - Small formatting changes
v3:
	- Use flatviews to help select regions for fuzzing 
	- Meson-related changes
    - Add some documentation
	- Improve minimalization script to trim write{bwlq} commands
v2:
	- Remove QOS dependency.
	- Add a custom crossover function
	- Fix broken minimization scripts
	- Fixes to the IO region and DMA handling code

This is a general virtual-device fuzzer, designed to fuzz devices over Port IO,
MMIO, and DMA.

To get started with this:
 1. Build the fuzzers (see docs/devel/fuzzing.txt)
    Note: Build with --enable-sanitizers, or create a "dictionary file":
    echo kw1=\"FUZZ\" > dict
    and pass it as an argument to libFuzzer with -dict=./dict
    This magic value is a command separator that lets the fuzzer perform
    multiple IO actions with a single input.

 2. Pick the qemu arguments you wish to fuzz:
    export QEMU_FUZZ_ARGS="-M q35 -device virtio-balloon"

 3. Tell the fuzzer which QOM objects or MemoryRegion names to fuzz. I find the
 "info qom-tree", "info qtree" and "info mtree" commands useful for identifying
 these. Supports globbing. Here I will try to simultaneously fuzz(for no good
 reason) virtio-balloon and e1000e, which is included by default in the q35:
    export QEMU_FUZZ_OBJECTS='virtio* e1000*'
    You can also try to fuzz the whole machine:
    export QEMU_FUZZ_OBJECTS='*'

 4. Run the fuzzer for 0 inputs. The fuzzer should output a list of
 MemoryRegions/PCI Devices it will try to fuzz. Confirm that these match your
 expectations.
    ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=general-fuzz -runs=0

 5. Run the fuzzer:
    ./i386-softmmu/qemu-fuzz-i386 --fuzz-target=general-fuzz 


Basically, at the core, this fuzzer is an interpreter that splits the input
into a series of commands, such as mmio_write, pio_write, etc. We structure
these commands to hit only MemoryRegions that are associated with the devices
specified in QEMU_FUZZ_OBJECTS. Additionally, these patches add "hooks" to
functions that are typically used by virtual-devices to read from RAM (DMA).
These hooks attempt to populate these DMA regions with fuzzed data, just in
time.

Some of the issues I have found or reproduced with this fuzzer:
https://bugs.launchpad.net/bugs/1525123
https://bugs.launchpad.net/bugs/1681439
https://bugs.launchpad.net/bugs/1777315
https://bugs.launchpad.net/bugs/1878034
https://bugs.launchpad.net/bugs/1878043
https://bugs.launchpad.net/bugs/1878054
https://bugs.launchpad.net/bugs/1878057
https://bugs.launchpad.net/bugs/1878067
https://bugs.launchpad.net/bugs/1878134
https://bugs.launchpad.net/bugs/1878136
https://bugs.launchpad.net/bugs/1878253
https://bugs.launchpad.net/bugs/1878255
https://bugs.launchpad.net/bugs/1878259
https://bugs.launchpad.net/bugs/1878263
https://bugs.launchpad.net/bugs/1878323
https://bugs.launchpad.net/bugs/1878641
https://bugs.launchpad.net/bugs/1878642
https://bugs.launchpad.net/bugs/1878645
https://bugs.launchpad.net/bugs/1878651
https://bugs.launchpad.net/bugs/1879223
https://bugs.launchpad.net/bugs/1879227
https://bugs.launchpad.net/bugs/1879531
https://bugs.launchpad.net/bugs/1880355
https://bugs.launchpad.net/bugs/1880539
https://bugs.launchpad.net/bugs/1884693
https://bugs.launchpad.net/bugs/1886362
https://bugs.launchpad.net/bugs/1887303
https://bugs.launchpad.net/bugs/1887309
https://bugs.launchpad.net/bugs/697510

Alexander Bulekov (16):
  memory: Add FlatView foreach function
  fuzz: Add general virtual-device fuzzer
  fuzz: Add PCI features to the general fuzzer
  fuzz: Add DMA support to the generic-fuzzer
  fuzz: Declare DMA Read callback function
  fuzz: Add fuzzer callbacks to DMA-read functions
  fuzz: Add support for custom crossover functions
  fuzz: add a DISABLE_PCI op to general-fuzzer
  fuzz: add a crossover function to generic-fuzzer
  scripts/oss-fuzz: Add script to reorder a general-fuzzer trace
  scripts/oss-fuzz: Add crash trace minimization script
  fuzz: Add instructions for using general-fuzz
  fuzz: add an "opaque" to the FuzzTarget struct
  fuzz: add general-fuzz configs for oss-fuzz
  fuzz: register predefined general-fuzz configs
  scripts/oss-fuzz: remove the general-fuzz target

 docs/devel/fuzzing.txt                        |  39 +
 include/exec/memory.h                         |  21 +
 include/exec/memory_ldst_cached.h.inc         |   3 +
 memory_ldst.c.inc                             |   4 +
 scripts/oss-fuzz/build.sh                     |   6 +
 scripts/oss-fuzz/minimize_qtest_trace.py      | 157 +++
 .../oss-fuzz/reorder_fuzzer_qtest_trace.py    | 103 ++
 softmmu/memory.c                              |  23 +
 softmmu/physmem.c                             |   2 +
 tests/qtest/fuzz/fuzz.c                       |  13 +
 tests/qtest/fuzz/fuzz.h                       |  28 +
 tests/qtest/fuzz/generic_fuzz.c               | 948 ++++++++++++++++++
 tests/qtest/fuzz/generic_fuzz_configs.h       | 121 +++
 tests/qtest/fuzz/meson.build                  |   1 +
 14 files changed, 1469 insertions(+)
 create mode 100755 scripts/oss-fuzz/minimize_qtest_trace.py
 create mode 100755 scripts/oss-fuzz/reorder_fuzzer_qtest_trace.py
 create mode 100644 tests/qtest/fuzz/generic_fuzz.c
 create mode 100644 tests/qtest/fuzz/generic_fuzz_configs.h

Comments

Thomas Huth Oct. 21, 2020, 1:24 p.m. UTC | #1
On 21/10/2020 03.07, Alexander Bulekov wrote:
> v5:

>     - Replace GArray-based predefined fuzzer configs with a static

>       struct array

>     - "General" -> "Generic"

>     - Fix bugs with wrong timeout denominator and skipping DMA memwrites

>       without QTEST_LOG

> v4:

>     - Replace yaml + c template-based oss-fuzz configs, with C code to

>       register a FuzzTarget for each config (as suggested by Paolo)

>     - Replicate the functionality of address_space_write_rom to ensure

>       matching behavior when QTEST_LOG is enabled

>     - Improve code documentation/comments

>     - Small formatting changes

> v3:

> 	- Use flatviews to help select regions for fuzzing 

> 	- Meson-related changes

>     - Add some documentation

> 	- Improve minimalization script to trim write{bwlq} commands

> v2:

> 	- Remove QOS dependency.

> 	- Add a custom crossover function

> 	- Fix broken minimization scripts

> 	- Fixes to the IO region and DMA handling code

> 

> This is a general virtual-device fuzzer, designed to fuzz devices over Port IO,

> MMIO, and DMA.


 Hi Alexander,

this fails to compile in the Gitlab-CI:

https://gitlab.com/huth/qemu/-/jobs/803091952#L2308

../softmmu/memory.c: In function 'flatview_for_each_range':
2309../softmmu/memory.c:663:24: error: incompatible type for argument 1 of 'cb'
2310         if (cb(fr->addr.start, fr->addr.size, fr->mr, opaque))
2311                ~~~~~~~~^~~~~~
2312../softmmu/memory.c:663:24: note: expected 'ram_addr_t' {aka 'unsigned
int'} but argument is of type 'Int128' {aka 'struct Int128'}
2313../softmmu/memory.c:663:40: error: incompatible type for argument 2 of 'cb'
2314         if (cb(fr->addr.start, fr->addr.size, fr->mr, opaque))
2315                                ~~~~~~~~^~~~~
2316../softmmu/memory.c:663:40: note: expected 'ram_addr_t' {aka 'unsigned
int'} but argument is of type 'Int128' {aka 'struct Int128'}

 Thomas