Hi Peter, The following changes since commit 48202c712412c803ddb56365c7bca322aa4e7506: Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210119-1' into staging (2021-01-19 15:47:23 +0000) are available in the Git repository at: https://gitlab.com/a1xndr/qemu.git tags/pull-request-2021-01-20 for you to fetch changes up to fae446ae7b6f746377186b3e19fd3f732a8b4325: fuzz: add virtio-9p configurations for fuzzing (2021-01-20 12:30:26 -0500) ---------------------------------------------------------------- * Add fuzzer configs for virtio-9p * Add fuzzer configs for PATA/SATA ide-hd and atapi devices * Remove a DMA callback check that was limitting the fuzzer * Improve debug info and documentation ---------------------------------------------------------------- Alexander Bulekov (7): fuzz: ignore address_space_map is_write flag fuzz: refine the ide/ahci fuzzer configs docs/fuzz: fix pre-meson path fuzz: log the arguments used to initialize QEMU fuzz: enable dynamic args for generic-fuzz configs docs/fuzz: add some information about OSS-Fuzz fuzz: add virtio-9p configurations for fuzzing docs/devel/fuzzing.rst | 31 ++++++++++++++++++++++++++++--- include/exec/memory.h | 8 +++----- include/exec/memory_ldst_cached.h.inc | 6 +++--- memory_ldst.c.inc | 8 ++++---- softmmu/memory.c | 5 ++--- softmmu/physmem.c | 4 ++-- tests/qtest/fuzz/fuzz.c | 11 ++++++++++- tests/qtest/fuzz/generic_fuzz.c | 19 ++++++++++++------- tests/qtest/fuzz/generic_fuzz_configs.h | 41 ++++++++++++++++++++++++++++++++++++++++- 9 files changed, 104 insertions(+), 29 deletions(-) Alexander Bulekov (7): fuzz: ignore address_space_map is_write flag fuzz: refine the ide/ahci fuzzer configs docs/fuzz: fix pre-meson path fuzz: log the arguments used to initialize QEMU fuzz: enable dynamic args for generic-fuzz configs docs/fuzz: add some information about OSS-Fuzz fuzz: add virtio-9p configurations for fuzzing docs/devel/fuzzing.rst | 31 +++++++++++++++++-- include/exec/memory.h | 8 ++--- include/exec/memory_ldst_cached.h.inc | 6 ++-- memory_ldst.c.inc | 8 ++--- softmmu/memory.c | 5 ++- softmmu/physmem.c | 4 +-- tests/qtest/fuzz/fuzz.c | 11 ++++++- tests/qtest/fuzz/generic_fuzz.c | 19 +++++++----- tests/qtest/fuzz/generic_fuzz_configs.h | 41 ++++++++++++++++++++++++- 9 files changed, 104 insertions(+), 29 deletions(-) -- 2.28.0
Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Thomas Huth <thuth@redhat.com> --- docs/devel/fuzzing.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/devel/fuzzing.rst b/docs/devel/fuzzing.rst index 6096242d99..5f5200c843 100644 --- a/docs/devel/fuzzing.rst +++ b/docs/devel/fuzzing.rst @@ -119,7 +119,7 @@ Adding a new fuzzer Coverage over virtual devices can be improved by adding additional fuzzers. Fuzzers are kept in ``tests/qtest/fuzz/`` and should be added to -``tests/qtest/fuzz/Makefile.include`` +``tests/qtest/fuzz/meson.build`` Fuzzers can rely on both qtest and libqos to communicate with virtual devices. @@ -128,8 +128,7 @@ Fuzzers can rely on both qtest and libqos to communicate with virtual devices. 2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers for reference. -3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the - corresponding object to fuzz-obj-y +3. Add the fuzzer to ``tests/qtest/fuzz/meson.build``. Fuzzers can be more-or-less thought of as special qtest programs which can modify the qtest commands and/or qtest command arguments based on inputs -- 2.28.0
We passed an is_write flag to the fuzz_dma_read_cb function to differentiate between the mapped DMA regions that need to be populated with fuzzed data, and those that don't. We simply passed through the address_space_map is_write parameter. The goal was to cut down on unnecessarily populating mapped DMA regions, when they are not read from. Unfortunately, nothing precludes code from reading from regions mapped with is_write=true. For example, see: https://lists.gnu.org/archive/html/qemu-devel/2021-01/msg04729.html This patch removes the is_write parameter to fuzz_dma_read_cb. As a result, we will fill all mapped DMA regions with fuzzed data, ignoring the specified transfer direction. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> --- include/exec/memory.h | 8 +++----- include/exec/memory_ldst_cached.h.inc | 6 +++--- memory_ldst.c.inc | 8 ++++---- softmmu/memory.c | 5 ++--- softmmu/physmem.c | 4 ++-- tests/qtest/fuzz/generic_fuzz.c | 9 +++------ 6 files changed, 17 insertions(+), 23 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 521d9901d7..0f89787de2 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -45,13 +45,11 @@ DECLARE_OBJ_CHECKERS(IOMMUMemoryRegion, IOMMUMemoryRegionClass, #ifdef CONFIG_FUZZ void fuzz_dma_read_cb(size_t addr, size_t len, - MemoryRegion *mr, - bool is_write); + MemoryRegion *mr); #else static inline void fuzz_dma_read_cb(size_t addr, size_t len, - MemoryRegion *mr, - bool is_write) + MemoryRegion *mr) { /* Do Nothing */ } @@ -2504,7 +2502,7 @@ address_space_read_cached(MemoryRegionCache *cache, hwaddr addr, void *buf, hwaddr len) { assert(addr < cache->len && len <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr); if (likely(cache->ptr)) { memcpy(buf, cache->ptr + addr, len); return MEMTX_OK; diff --git a/include/exec/memory_ldst_cached.h.inc b/include/exec/memory_ldst_cached.h.inc index 01efad62de..7bc8790d34 100644 --- a/include/exec/memory_ldst_cached.h.inc +++ b/include/exec/memory_ldst_cached.h.inc @@ -28,7 +28,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(l)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 4 <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, 4, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, 4, cache->mrs.mr); if (likely(cache->ptr)) { return LD_P(l)(cache->ptr + addr); } else { @@ -40,7 +40,7 @@ static inline uint64_t ADDRESS_SPACE_LD_CACHED(q)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 8 <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, 8, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, 8, cache->mrs.mr); if (likely(cache->ptr)) { return LD_P(q)(cache->ptr + addr); } else { @@ -52,7 +52,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 2 <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr); if (likely(cache->ptr)) { return LD_P(uw)(cache->ptr + addr); } else { diff --git a/memory_ldst.c.inc b/memory_ldst.c.inc index 2fed2de18e..b56e961967 100644 --- a/memory_ldst.c.inc +++ b/memory_ldst.c.inc @@ -42,7 +42,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL, MO_32 | devend_memop(endian), attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 4, mr, false); + fuzz_dma_read_cb(addr, 4, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -111,7 +111,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL, MO_64 | devend_memop(endian), attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 8, mr, false); + fuzz_dma_read_cb(addr, 8, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -177,7 +177,7 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL, r = memory_region_dispatch_read(mr, addr1, &val, MO_8, attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 1, mr, false); + fuzz_dma_read_cb(addr, 1, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); val = ldub_p(ptr); r = MEMTX_OK; @@ -215,7 +215,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL, MO_16 | devend_memop(endian), attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 2, mr, false); + fuzz_dma_read_cb(addr, 2, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: diff --git a/softmmu/memory.c b/softmmu/memory.c index 333e1ed7b0..4fc0071dcd 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1440,7 +1440,7 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr, unsigned size = memop_size(op); MemTxResult r; - fuzz_dma_read_cb(addr, size, mr, false); + fuzz_dma_read_cb(addr, size, mr); if (!memory_region_access_valid(mr, addr, size, false, attrs)) { *pval = unassigned_mem_read(mr, addr, size); return MEMTX_DECODE_ERROR; @@ -3282,8 +3282,7 @@ void memory_region_init_rom_device(MemoryRegion *mr, #ifdef CONFIG_FUZZ void __attribute__((weak)) fuzz_dma_read_cb(size_t addr, size_t len, - MemoryRegion *mr, - bool is_write) + MemoryRegion *mr) { } #endif diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 6301f4f0a5..5aaec2f2c1 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -2824,7 +2824,7 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr, stn_he_p(buf, l, val); } else { /* RAM case */ - fuzz_dma_read_cb(addr, len, mr, false); + fuzz_dma_read_cb(addr, len, mr); ram_ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false); memcpy(buf, ram_ptr, l); } @@ -3185,7 +3185,7 @@ void *address_space_map(AddressSpace *as, memory_region_ref(mr); *plen = flatview_extend_translation(fv, addr, len, mr, xlat, l, is_write, attrs); - fuzz_dma_read_cb(addr, *plen, mr, is_write); + fuzz_dma_read_cb(addr, *plen, mr); ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); return ptr; diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index be76d47d2d..deb74f15be 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -175,7 +175,7 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) * generic_fuzz(), avoiding potential race-conditions, which we don't have * a good way for reproducing right now. */ -void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write) +void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr) { /* Are we in the generic-fuzzer or are we using another fuzz-target? */ if (!qts_global) { @@ -187,14 +187,11 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write) * - We have no DMA patterns defined * - The length of the DMA read request is zero * - The DMA read is hitting an MR other than the machine's main RAM - * - The DMA request is not a read (what happens for a address_space_map - * with is_write=True? Can the device use the same pointer to do reads?) * - The DMA request hits past the bounds of our RAM */ if (dma_patterns->len == 0 || len == 0 || mr != current_machine->ram - || is_write || addr > current_machine->ram_size) { return; } @@ -213,12 +210,12 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write) double_fetch = true; if (addr < region.addr && avoid_double_fetches) { - fuzz_dma_read_cb(addr, region.addr - addr, mr, is_write); + fuzz_dma_read_cb(addr, region.addr - addr, mr); } if (addr + len > region.addr + region.size && avoid_double_fetches) { fuzz_dma_read_cb(region.addr + region.size, - addr + len - (region.addr + region.size), mr, is_write); + addr + len - (region.addr + region.size), mr); } return; } -- 2.28.0
This is useful for building reproducers. Instead checking the code or the QEMU_FUZZ_ARGS, the arguments are at the top of the crash log. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Thomas Huth <thuth@redhat.com> --- tests/qtest/fuzz/fuzz.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index 238866a037..496d11a231 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -159,6 +159,8 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) char *target_name; const char *bindir; char *datadir; + GString *cmd_line; + gchar *pretty_cmd_line; bool serialize = false; /* Initialize qgraph and modules */ @@ -217,7 +219,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) } /* Run QEMU's softmmu main with the fuzz-target dependent arguments */ - GString *cmd_line = fuzz_target->get_init_cmdline(fuzz_target); + cmd_line = fuzz_target->get_init_cmdline(fuzz_target); g_string_append_printf(cmd_line, " %s -qtest /dev/null ", getenv("QTEST_LOG") ? "" : "-qtest-log none"); @@ -226,6 +228,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) wordexp(cmd_line->str, &result, 0); g_string_free(cmd_line, true); + if (getenv("QTEST_LOG")) { + pretty_cmd_line = g_strjoinv(" ", result.we_wordv + 1); + printf("Starting %s with Arguments: %s\n", + result.we_wordv[0], pretty_cmd_line); + g_free(pretty_cmd_line); + } + qemu_init(result.we_wordc, result.we_wordv, NULL); /* re-enable the rcu atfork, which was previously disabled in qemu_init */ -- 2.28.0
Disks work differently depending on the x86 machine type (SATA vs PATA). Additionally, we should fuzz the atapi code paths, which might contain vulnerabilities such as CVE-2020-29443. This patch adds hard-disk and cdrom generic-fuzzer configs for both the pc (PATA) and q35 (SATA) machine types. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> --- tests/qtest/fuzz/generic_fuzz_configs.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 7fed035345..aa4c03f1ae 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -85,10 +85,28 @@ const generic_fuzz_config predefined_configs[] = { .objects = "intel-hda", },{ .name = "ide-hd", + .args = "-machine pc -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device ide-hd,drive=disk0", + .objects = "*ide*", + },{ + .name = "ide-atapi", + .args = "-machine pc -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device ide-cd,drive=disk0", + .objects = "*ide*", + },{ + .name = "ahci-hd", .args = "-machine q35 -nodefaults " "-drive file=null-co://,if=none,format=raw,id=disk0 " "-device ide-hd,drive=disk0", - .objects = "ahci*", + .objects = "*ahci*", + },{ + .name = "ahci-atapi", + .args = "-machine q35 -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device ide-cd,drive=disk0", + .objects = "*ahci*", },{ .name = "floppy", .args = "-machine pc -nodefaults -device floppy,id=floppy0 " -- 2.28.0
Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Thomas Huth <thuth@redhat.com> --- docs/devel/fuzzing.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/devel/fuzzing.rst b/docs/devel/fuzzing.rst index 6096242d99..5f5200c843 100644 --- a/docs/devel/fuzzing.rst +++ b/docs/devel/fuzzing.rst @@ -119,7 +119,7 @@ Adding a new fuzzer Coverage over virtual devices can be improved by adding additional fuzzers. Fuzzers are kept in ``tests/qtest/fuzz/`` and should be added to -``tests/qtest/fuzz/Makefile.include`` +``tests/qtest/fuzz/meson.build`` Fuzzers can rely on both qtest and libqos to communicate with virtual devices. @@ -128,8 +128,7 @@ Fuzzers can rely on both qtest and libqos to communicate with virtual devices. 2. Write the fuzzing code using the libqtest/libqos API. See existing fuzzers for reference. -3. Register the fuzzer in ``tests/fuzz/Makefile.include`` by appending the - corresponding object to fuzz-obj-y +3. Add the fuzzer to ``tests/qtest/fuzz/meson.build``. Fuzzers can be more-or-less thought of as special qtest programs which can modify the qtest commands and/or qtest command arguments based on inputs -- 2.28.0
For some device configurations, it is useful to configure some resources, and adjust QEMU arguments at runtime, prior to fuzzing. This patch adds an "argfunc" to generic the generic_fuzz_config. When specified, it is responsible for configuring the resources and returning a string containing the corresponding QEMU arguments. This can be useful for targets that rely on e.g.: * a temporary qcow2 image * a temporary directory * an unused TCP port used to bind the VNC server Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Thomas Huth <thuth@redhat.com> --- tests/qtest/fuzz/generic_fuzz.c | 10 +++++++++- tests/qtest/fuzz/generic_fuzz_configs.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index be76d47d2d..6adf62a5be 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -936,12 +936,20 @@ static GString *generic_fuzz_cmdline(FuzzTarget *t) static GString *generic_fuzz_predefined_config_cmdline(FuzzTarget *t) { + gchar *args; const generic_fuzz_config *config; g_assert(t->opaque); config = t->opaque; setenv("QEMU_AVOID_DOUBLE_FETCH", "1", 1); - setenv("QEMU_FUZZ_ARGS", config->args, 1); + if (config->argfunc) { + args = config->argfunc(); + setenv("QEMU_FUZZ_ARGS", args, 1); + g_free(args); + } else { + g_assert_nonnull(config->args); + setenv("QEMU_FUZZ_ARGS", config->args, 1); + } setenv("QEMU_FUZZ_OBJECTS", config->objects, 1); return generic_fuzz_cmdline(t); } diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 7fed035345..1a133655ee 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -16,6 +16,7 @@ typedef struct generic_fuzz_config { const char *name, *args, *objects; + gchar* (*argfunc)(void); /* Result must be freeable by g_free() */ } generic_fuzz_config; const generic_fuzz_config predefined_configs[] = { -- 2.28.0
Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> --- docs/devel/fuzzing.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/devel/fuzzing.rst b/docs/devel/fuzzing.rst index 5f5200c843..b9bb07988b 100644 --- a/docs/devel/fuzzing.rst +++ b/docs/devel/fuzzing.rst @@ -180,6 +180,32 @@ To ensure that these env variables have been configured correctly, we can use:: The output should contain a complete list of matched MemoryRegions. +OSS-Fuzz +-------- +QEMU is continuously fuzzed on `OSS-Fuzz` __(https://github.com/google/oss-fuzz). +By default, the OSS-Fuzz build will try to fuzz every fuzz-target. Since the +generic-fuzz target requires additional information provided in environment +variables, we pre-define some generic-fuzz configs in +``tests/qtest/fuzz/generic_fuzz_configs.h``. Each config must specify: + * ``.name``: To identify the fuzzer config + * ``.args`` OR ``.argfunc``: A string or pointer to a function returning a + string. These strings are used to specify the ``QEMU_FUZZ_ARGS`` + environment variable. ``argfunc`` is useful when the config relies on e.g. + a dynamically created temp directory, or a free tcp/udp port. + * ``.objects``: A string that specifies the ``QEMU_FUZZ_OBJECTS`` environment + variable. + +To fuzz additional devices/device configuration on OSS-Fuzz: + * Send patches for a new device-specific fuzzer + * Send patches for a new generic-fuzz config + +Build details: + * `The basic Dockerfile that sets up the environment for building QEMU's + fuzzers on OSS-Fuzz + <https://github.com/google/oss-fuzz/blob/master/projects/qemu/Dockerfile>`_ + * The script responsible for building the fuzzers: + ``scripts/oss-fuzz/build.sh`` + Implementation Details / Fuzzer Lifecycle ----------------------------------------- -- 2.28.0
This is useful for building reproducers. Instead checking the code or the QEMU_FUZZ_ARGS, the arguments are at the top of the crash log. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Thomas Huth <thuth@redhat.com> --- tests/qtest/fuzz/fuzz.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index 238866a037..496d11a231 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -159,6 +159,8 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) char *target_name; const char *bindir; char *datadir; + GString *cmd_line; + gchar *pretty_cmd_line; bool serialize = false; /* Initialize qgraph and modules */ @@ -217,7 +219,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) } /* Run QEMU's softmmu main with the fuzz-target dependent arguments */ - GString *cmd_line = fuzz_target->get_init_cmdline(fuzz_target); + cmd_line = fuzz_target->get_init_cmdline(fuzz_target); g_string_append_printf(cmd_line, " %s -qtest /dev/null ", getenv("QTEST_LOG") ? "" : "-qtest-log none"); @@ -226,6 +228,13 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) wordexp(cmd_line->str, &result, 0); g_string_free(cmd_line, true); + if (getenv("QTEST_LOG")) { + pretty_cmd_line = g_strjoinv(" ", result.we_wordv + 1); + printf("Starting %s with Arguments: %s\n", + result.we_wordv[0], pretty_cmd_line); + g_free(pretty_cmd_line); + } + qemu_init(result.we_wordc, result.we_wordv, NULL); /* re-enable the rcu atfork, which was previously disabled in qemu_init */ -- 2.28.0
virtio-9p devices are often used to expose a virtual-filesystem to the guest. There have been some bugs reported in this device, such as CVE-2018-19364, and CVE-2021-20181. We should fuzz this device This patch adds two virtio-9p configurations: * One with the widely used -fsdev local driver. This driver leaks some state in the form of files/directories created in the shared dir. * One with the synth driver. While it is not used in the real world, this driver won't leak leak state between fuzz inputs. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> --- tests/qtest/fuzz/generic_fuzz_configs.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 1a133655ee..f99657cdbc 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -19,6 +19,16 @@ typedef struct generic_fuzz_config { gchar* (*argfunc)(void); /* Result must be freeable by g_free() */ } generic_fuzz_config; +static inline gchar *generic_fuzzer_virtio_9p_args(void){ + char tmpdir[] = "/tmp/qemu-fuzz.XXXXXX"; + g_assert_nonnull(mkdtemp(tmpdir)); + + return g_strdup_printf("-machine q35 -nodefaults " + "-device virtio-9p,fsdev=hshare,mount_tag=hshare " + "-fsdev local,id=hshare,path=%s,security_model=mapped-xattr," + "writeout=immediate,fmode=0600,dmode=0700", tmpdir); +} + const generic_fuzz_config predefined_configs[] = { { .name = "virtio-net-pci-slirp", @@ -60,6 +70,16 @@ const generic_fuzz_config predefined_configs[] = { .name = "virtio-mouse", .args = "-machine q35 -nodefaults -device virtio-mouse", .objects = "virtio*", + },{ + .name = "virtio-9p", + .argfunc = generic_fuzzer_virtio_9p_args, + .objects = "virtio*", + },{ + .name = "virtio-9p-synth", + .args = "-machine q35 -nodefaults " + "-device virtio-9p,fsdev=hshare,mount_tag=hshare " + "-fsdev synth,id=hshare", + .objects = "virtio*", },{ .name = "e1000", .args = "-M q35 -nodefaults " -- 2.28.0
For some device configurations, it is useful to configure some resources, and adjust QEMU arguments at runtime, prior to fuzzing. This patch adds an "argfunc" to generic the generic_fuzz_config. When specified, it is responsible for configuring the resources and returning a string containing the corresponding QEMU arguments. This can be useful for targets that rely on e.g.: * a temporary qcow2 image * a temporary directory * an unused TCP port used to bind the VNC server Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Thomas Huth <thuth@redhat.com> --- tests/qtest/fuzz/generic_fuzz.c | 10 +++++++++- tests/qtest/fuzz/generic_fuzz_configs.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index deb74f15be..ee8c17a04c 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -933,12 +933,20 @@ static GString *generic_fuzz_cmdline(FuzzTarget *t) static GString *generic_fuzz_predefined_config_cmdline(FuzzTarget *t) { + gchar *args; const generic_fuzz_config *config; g_assert(t->opaque); config = t->opaque; setenv("QEMU_AVOID_DOUBLE_FETCH", "1", 1); - setenv("QEMU_FUZZ_ARGS", config->args, 1); + if (config->argfunc) { + args = config->argfunc(); + setenv("QEMU_FUZZ_ARGS", args, 1); + g_free(args); + } else { + g_assert_nonnull(config->args); + setenv("QEMU_FUZZ_ARGS", config->args, 1); + } setenv("QEMU_FUZZ_OBJECTS", config->objects, 1); return generic_fuzz_cmdline(t); } diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index aa4c03f1ae..51e69c6e42 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -16,6 +16,7 @@ typedef struct generic_fuzz_config { const char *name, *args, *objects; + gchar* (*argfunc)(void); /* Result must be freeable by g_free() */ } generic_fuzz_config; const generic_fuzz_config predefined_configs[] = { -- 2.28.0
Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> --- docs/devel/fuzzing.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/devel/fuzzing.rst b/docs/devel/fuzzing.rst index 5f5200c843..b9bb07988b 100644 --- a/docs/devel/fuzzing.rst +++ b/docs/devel/fuzzing.rst @@ -180,6 +180,32 @@ To ensure that these env variables have been configured correctly, we can use:: The output should contain a complete list of matched MemoryRegions. +OSS-Fuzz +-------- +QEMU is continuously fuzzed on `OSS-Fuzz` __(https://github.com/google/oss-fuzz). +By default, the OSS-Fuzz build will try to fuzz every fuzz-target. Since the +generic-fuzz target requires additional information provided in environment +variables, we pre-define some generic-fuzz configs in +``tests/qtest/fuzz/generic_fuzz_configs.h``. Each config must specify: + * ``.name``: To identify the fuzzer config + * ``.args`` OR ``.argfunc``: A string or pointer to a function returning a + string. These strings are used to specify the ``QEMU_FUZZ_ARGS`` + environment variable. ``argfunc`` is useful when the config relies on e.g. + a dynamically created temp directory, or a free tcp/udp port. + * ``.objects``: A string that specifies the ``QEMU_FUZZ_OBJECTS`` environment + variable. + +To fuzz additional devices/device configuration on OSS-Fuzz: + * Send patches for a new device-specific fuzzer + * Send patches for a new generic-fuzz config + +Build details: + * `The basic Dockerfile that sets up the environment for building QEMU's + fuzzers on OSS-Fuzz + <https://github.com/google/oss-fuzz/blob/master/projects/qemu/Dockerfile>`_ + * The script responsible for building the fuzzers: + ``scripts/oss-fuzz/build.sh`` + Implementation Details / Fuzzer Lifecycle ----------------------------------------- -- 2.28.0
We passed an is_write flag to the fuzz_dma_read_cb function to differentiate between the mapped DMA regions that need to be populated with fuzzed data, and those that don't. We simply passed through the address_space_map is_write parameter. The goal was to cut down on unnecessarily populating mapped DMA regions, when they are not read from. Unfortunately, nothing precludes code from reading from regions mapped with is_write=true. For example, see: https://lists.gnu.org/archive/html/qemu-devel/2021-01/msg04729.html This patch removes the is_write parameter to fuzz_dma_read_cb. As a result, we will fill all mapped DMA regions with fuzzed data, ignoring the specified transfer direction. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> --- include/exec/memory.h | 8 +++----- include/exec/memory_ldst_cached.h.inc | 6 +++--- memory_ldst.c.inc | 8 ++++---- softmmu/memory.c | 5 ++--- softmmu/physmem.c | 4 ++-- tests/qtest/fuzz/generic_fuzz.c | 9 +++------ 6 files changed, 17 insertions(+), 23 deletions(-) diff --git a/include/exec/memory.h b/include/exec/memory.h index 521d9901d7..0f89787de2 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -45,13 +45,11 @@ DECLARE_OBJ_CHECKERS(IOMMUMemoryRegion, IOMMUMemoryRegionClass, #ifdef CONFIG_FUZZ void fuzz_dma_read_cb(size_t addr, size_t len, - MemoryRegion *mr, - bool is_write); + MemoryRegion *mr); #else static inline void fuzz_dma_read_cb(size_t addr, size_t len, - MemoryRegion *mr, - bool is_write) + MemoryRegion *mr) { /* Do Nothing */ } @@ -2504,7 +2502,7 @@ address_space_read_cached(MemoryRegionCache *cache, hwaddr addr, void *buf, hwaddr len) { assert(addr < cache->len && len <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr); if (likely(cache->ptr)) { memcpy(buf, cache->ptr + addr, len); return MEMTX_OK; diff --git a/include/exec/memory_ldst_cached.h.inc b/include/exec/memory_ldst_cached.h.inc index 01efad62de..7bc8790d34 100644 --- a/include/exec/memory_ldst_cached.h.inc +++ b/include/exec/memory_ldst_cached.h.inc @@ -28,7 +28,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(l)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 4 <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, 4, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, 4, cache->mrs.mr); if (likely(cache->ptr)) { return LD_P(l)(cache->ptr + addr); } else { @@ -40,7 +40,7 @@ static inline uint64_t ADDRESS_SPACE_LD_CACHED(q)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 8 <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, 8, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, 8, cache->mrs.mr); if (likely(cache->ptr)) { return LD_P(q)(cache->ptr + addr); } else { @@ -52,7 +52,7 @@ static inline uint32_t ADDRESS_SPACE_LD_CACHED(uw)(MemoryRegionCache *cache, hwaddr addr, MemTxAttrs attrs, MemTxResult *result) { assert(addr < cache->len && 2 <= cache->len - addr); - fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr, false); + fuzz_dma_read_cb(cache->xlat + addr, 2, cache->mrs.mr); if (likely(cache->ptr)) { return LD_P(uw)(cache->ptr + addr); } else { diff --git a/memory_ldst.c.inc b/memory_ldst.c.inc index 2fed2de18e..b56e961967 100644 --- a/memory_ldst.c.inc +++ b/memory_ldst.c.inc @@ -42,7 +42,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL, MO_32 | devend_memop(endian), attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 4, mr, false); + fuzz_dma_read_cb(addr, 4, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -111,7 +111,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL, MO_64 | devend_memop(endian), attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 8, mr, false); + fuzz_dma_read_cb(addr, 8, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: @@ -177,7 +177,7 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL, r = memory_region_dispatch_read(mr, addr1, &val, MO_8, attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 1, mr, false); + fuzz_dma_read_cb(addr, 1, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); val = ldub_p(ptr); r = MEMTX_OK; @@ -215,7 +215,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL, MO_16 | devend_memop(endian), attrs); } else { /* RAM case */ - fuzz_dma_read_cb(addr, 2, mr, false); + fuzz_dma_read_cb(addr, 2, mr); ptr = qemu_map_ram_ptr(mr->ram_block, addr1); switch (endian) { case DEVICE_LITTLE_ENDIAN: diff --git a/softmmu/memory.c b/softmmu/memory.c index 333e1ed7b0..4fc0071dcd 100644 --- a/softmmu/memory.c +++ b/softmmu/memory.c @@ -1440,7 +1440,7 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr, unsigned size = memop_size(op); MemTxResult r; - fuzz_dma_read_cb(addr, size, mr, false); + fuzz_dma_read_cb(addr, size, mr); if (!memory_region_access_valid(mr, addr, size, false, attrs)) { *pval = unassigned_mem_read(mr, addr, size); return MEMTX_DECODE_ERROR; @@ -3282,8 +3282,7 @@ void memory_region_init_rom_device(MemoryRegion *mr, #ifdef CONFIG_FUZZ void __attribute__((weak)) fuzz_dma_read_cb(size_t addr, size_t len, - MemoryRegion *mr, - bool is_write) + MemoryRegion *mr) { } #endif diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 6301f4f0a5..5aaec2f2c1 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -2824,7 +2824,7 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr, stn_he_p(buf, l, val); } else { /* RAM case */ - fuzz_dma_read_cb(addr, len, mr, false); + fuzz_dma_read_cb(addr, len, mr); ram_ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l, false); memcpy(buf, ram_ptr, l); } @@ -3185,7 +3185,7 @@ void *address_space_map(AddressSpace *as, memory_region_ref(mr); *plen = flatview_extend_translation(fv, addr, len, mr, xlat, l, is_write, attrs); - fuzz_dma_read_cb(addr, *plen, mr, is_write); + fuzz_dma_read_cb(addr, *plen, mr); ptr = qemu_ram_ptr_length(mr->ram_block, xlat, plen, true); return ptr; diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index 6adf62a5be..ee8c17a04c 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -175,7 +175,7 @@ static int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr) * generic_fuzz(), avoiding potential race-conditions, which we don't have * a good way for reproducing right now. */ -void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write) +void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr) { /* Are we in the generic-fuzzer or are we using another fuzz-target? */ if (!qts_global) { @@ -187,14 +187,11 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write) * - We have no DMA patterns defined * - The length of the DMA read request is zero * - The DMA read is hitting an MR other than the machine's main RAM - * - The DMA request is not a read (what happens for a address_space_map - * with is_write=True? Can the device use the same pointer to do reads?) * - The DMA request hits past the bounds of our RAM */ if (dma_patterns->len == 0 || len == 0 || mr != current_machine->ram - || is_write || addr > current_machine->ram_size) { return; } @@ -213,12 +210,12 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr, bool is_write) double_fetch = true; if (addr < region.addr && avoid_double_fetches) { - fuzz_dma_read_cb(addr, region.addr - addr, mr, is_write); + fuzz_dma_read_cb(addr, region.addr - addr, mr); } if (addr + len > region.addr + region.size && avoid_double_fetches) { fuzz_dma_read_cb(region.addr + region.size, - addr + len - (region.addr + region.size), mr, is_write); + addr + len - (region.addr + region.size), mr); } return; } -- 2.28.0
virtio-9p devices are often used to expose a virtual-filesystem to the guest. There have been some bugs reported in this device, such as CVE-2018-19364, and CVE-2021-20181. We should fuzz this device This patch adds two virtio-9p configurations: * One with the widely used -fsdev local driver. This driver leaks some state in the form of files/directories created in the shared dir. * One with the synth driver. While it is not used in the real world, this driver won't leak leak state between fuzz inputs. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> --- tests/qtest/fuzz/generic_fuzz_configs.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 51e69c6e42..5d599765c4 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -19,6 +19,16 @@ typedef struct generic_fuzz_config { gchar* (*argfunc)(void); /* Result must be freeable by g_free() */ } generic_fuzz_config; +static inline gchar *generic_fuzzer_virtio_9p_args(void){ + char tmpdir[] = "/tmp/qemu-fuzz.XXXXXX"; + g_assert_nonnull(mkdtemp(tmpdir)); + + return g_strdup_printf("-machine q35 -nodefaults " + "-device virtio-9p,fsdev=hshare,mount_tag=hshare " + "-fsdev local,id=hshare,path=%s,security_model=mapped-xattr," + "writeout=immediate,fmode=0600,dmode=0700", tmpdir); +} + const generic_fuzz_config predefined_configs[] = { { .name = "virtio-net-pci-slirp", @@ -60,6 +70,16 @@ const generic_fuzz_config predefined_configs[] = { .name = "virtio-mouse", .args = "-machine q35 -nodefaults -device virtio-mouse", .objects = "virtio*", + },{ + .name = "virtio-9p", + .argfunc = generic_fuzzer_virtio_9p_args, + .objects = "virtio*", + },{ + .name = "virtio-9p-synth", + .args = "-machine q35 -nodefaults " + "-device virtio-9p,fsdev=hshare,mount_tag=hshare " + "-fsdev synth,id=hshare", + .objects = "virtio*", },{ .name = "e1000", .args = "-M q35 -nodefaults " -- 2.28.0
Disks work differently depending on the x86 machine type (SATA vs PATA). Additionally, we should fuzz the atapi code paths, which might contain vulnerabilities such as CVE-2020-29443. This patch adds hard-disk and cdrom generic-fuzzer configs for both the pc (PATA) and q35 (SATA) machine types. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Acked-by: Thomas Huth <thuth@redhat.com> --- tests/qtest/fuzz/generic_fuzz_configs.h | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index f99657cdbc..5d599765c4 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -106,10 +106,28 @@ const generic_fuzz_config predefined_configs[] = { .objects = "intel-hda", },{ .name = "ide-hd", + .args = "-machine pc -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device ide-hd,drive=disk0", + .objects = "*ide*", + },{ + .name = "ide-atapi", + .args = "-machine pc -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device ide-cd,drive=disk0", + .objects = "*ide*", + },{ + .name = "ahci-hd", .args = "-machine q35 -nodefaults " "-drive file=null-co://,if=none,format=raw,id=disk0 " "-device ide-hd,drive=disk0", - .objects = "ahci*", + .objects = "*ahci*", + },{ + .name = "ahci-atapi", + .args = "-machine q35 -nodefaults " + "-drive file=null-co://,if=none,format=raw,id=disk0 " + "-device ide-cd,drive=disk0", + .objects = "*ahci*", },{ .name = "floppy", .args = "-machine pc -nodefaults -device floppy,id=floppy0 " -- 2.28.0
Nack
On 210120 1235, Alexander Bulekov wrote:
> Hi Peter,
>
> The following changes since commit 48202c712412c803ddb56365c7bca322aa4e7506:
>
> Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210119-1' into staging (2021-01-19 15:47:23 +0000)
>
> are available in the Git repository at:
>
> https://gitlab.com/a1xndr/qemu.git tags/pull-request-2021-01-20
>
> for you to fetch changes up to fae446ae7b6f746377186b3e19fd3f732a8b4325:
>
> fuzz: add virtio-9p configurations for fuzzing (2021-01-20 12:30:26 -0500)
>
> ----------------------------------------------------------------
> * Add fuzzer configs for virtio-9p
> * Add fuzzer configs for PATA/SATA ide-hd and atapi devices
> * Remove a DMA callback check that was limitting the fuzzer
> * Improve debug info and documentation
>
> ----------------------------------------------------------------
> Alexander Bulekov (7):
> fuzz: ignore address_space_map is_write flag
> fuzz: refine the ide/ahci fuzzer configs
> docs/fuzz: fix pre-meson path
> fuzz: log the arguments used to initialize QEMU
> fuzz: enable dynamic args for generic-fuzz configs
> docs/fuzz: add some information about OSS-Fuzz
> fuzz: add virtio-9p configurations for fuzzing
>
> docs/devel/fuzzing.rst | 31 ++++++++++++++++++++++++++++---
> include/exec/memory.h | 8 +++-----
> include/exec/memory_ldst_cached.h.inc | 6 +++---
> memory_ldst.c.inc | 8 ++++----
> softmmu/memory.c | 5 ++---
> softmmu/physmem.c | 4 ++--
> tests/qtest/fuzz/fuzz.c | 11 ++++++++++-
> tests/qtest/fuzz/generic_fuzz.c | 19 ++++++++++++-------
> tests/qtest/fuzz/generic_fuzz_configs.h | 41 ++++++++++++++++++++++++++++++++++++++++-
> 9 files changed, 104 insertions(+), 29 deletions(-)
>
> Alexander Bulekov (7):
> fuzz: ignore address_space_map is_write flag
> fuzz: refine the ide/ahci fuzzer configs
> docs/fuzz: fix pre-meson path
> fuzz: log the arguments used to initialize QEMU
> fuzz: enable dynamic args for generic-fuzz configs
> docs/fuzz: add some information about OSS-Fuzz
> fuzz: add virtio-9p configurations for fuzzing
>
> docs/devel/fuzzing.rst | 31 +++++++++++++++++--
> include/exec/memory.h | 8 ++---
> include/exec/memory_ldst_cached.h.inc | 6 ++--
> memory_ldst.c.inc | 8 ++---
> softmmu/memory.c | 5 ++-
> softmmu/physmem.c | 4 +--
> tests/qtest/fuzz/fuzz.c | 11 ++++++-
> tests/qtest/fuzz/generic_fuzz.c | 19 +++++++-----
> tests/qtest/fuzz/generic_fuzz_configs.h | 41 ++++++++++++++++++++++++-
> 9 files changed, 104 insertions(+), 29 deletions(-)
>
> --
> 2.28.0
>