From c887d3339e5dc80ef9cec20a79d385ae36f9a13c Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 26 Jan 2021 12:16:37 +0100 Subject: tests/qtest: Only run fuzz-megasas-test if megasas device is available This test fails when QEMU is built without the megasas device, restrict it to its availability. Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Signed-off-by: Paolo Bonzini --- tests/qtest/fuzz-megasas-test.c | 49 +++++++++++++++++++++++++++++++++++++++++ tests/qtest/fuzz-test.c | 25 --------------------- tests/qtest/meson.build | 4 +++- 3 files changed, 52 insertions(+), 26 deletions(-) create mode 100644 tests/qtest/fuzz-megasas-test.c (limited to 'tests') diff --git a/tests/qtest/fuzz-megasas-test.c b/tests/qtest/fuzz-megasas-test.c new file mode 100644 index 0000000000..940a76bf25 --- /dev/null +++ b/tests/qtest/fuzz-megasas-test.c @@ -0,0 +1,49 @@ +/* + * QTest fuzzer-generated testcase for megasas device + * + * Copyright (c) 2020 Li Qiang + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" + +#include "libqos/libqtest.h" + +/* + * This used to trigger the assert in scsi_dma_complete + * https://bugs.launchpad.net/qemu/+bug/1878263 + */ +static void test_lp1878263_megasas_zero_iov_cnt(void) +{ + QTestState *s; + + s = qtest_init("-nographic -monitor none -serial none " + "-M q35 -device megasas -device scsi-cd,drive=null0 " + "-blockdev driver=null-co,read-zeroes=on,node-name=null0"); + qtest_outl(s, 0xcf8, 0x80001818); + qtest_outl(s, 0xcfc, 0xc101); + qtest_outl(s, 0xcf8, 0x8000181c); + qtest_outl(s, 0xcf8, 0x80001804); + qtest_outw(s, 0xcfc, 0x7); + qtest_outl(s, 0xcf8, 0x8000186a); + qtest_writeb(s, 0x14, 0xfe); + qtest_writeb(s, 0x0, 0x02); + qtest_outb(s, 0xc1c0, 0x17); + qtest_quit(s); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qtest_add_func("fuzz/test_lp1878263_megasas_zero_iov_cnt", + test_lp1878263_megasas_zero_iov_cnt); + } + + return g_test_run(); +} diff --git a/tests/qtest/fuzz-test.c b/tests/qtest/fuzz-test.c index 6f161c93be..631feaf0eb 100644 --- a/tests/qtest/fuzz-test.c +++ b/tests/qtest/fuzz-test.c @@ -11,29 +11,6 @@ #include "libqos/libqtest.h" -/* - * This used to trigger the assert in scsi_dma_complete - * https://bugs.launchpad.net/qemu/+bug/1878263 - */ -static void test_lp1878263_megasas_zero_iov_cnt(void) -{ - QTestState *s; - - s = qtest_init("-nographic -monitor none -serial none " - "-M q35 -device megasas -device scsi-cd,drive=null0 " - "-blockdev driver=null-co,read-zeroes=on,node-name=null0"); - qtest_outl(s, 0xcf8, 0x80001818); - qtest_outl(s, 0xcfc, 0xc101); - qtest_outl(s, 0xcf8, 0x8000181c); - qtest_outl(s, 0xcf8, 0x80001804); - qtest_outw(s, 0xcfc, 0x7); - qtest_outl(s, 0xcf8, 0x8000186a); - qtest_writeb(s, 0x14, 0xfe); - qtest_writeb(s, 0x0, 0x02); - qtest_outb(s, 0xc1c0, 0x17); - qtest_quit(s); -} - static void test_lp1878642_pci_bus_get_irq_level_assert(void) { QTestState *s; @@ -103,8 +80,6 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { - qtest_add_func("fuzz/test_lp1878263_megasas_zero_iov_cnt", - test_lp1878263_megasas_zero_iov_cnt); qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert", test_lp1878642_pci_bus_get_irq_level_assert); qtest_add_func("fuzz/test_mmio_oob_from_memory_region_cache", diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 66ee9fbf45..536991cdb8 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -17,7 +17,9 @@ slow_qtests = { 'test-hmp' : 120, } -qtests_generic = [ +qtests_generic = \ + (config_all_devices.has_key('CONFIG_MEGASAS_SCSI_PCI') ? ['fuzz-megasas-test'] : []) + \ + [ 'cdrom-test', 'device-introspect-test', 'machine-none-test', -- cgit v1.2.3-55-g7522 From b43957dcdda3c6190b94a0d186897f8fc8ecec7a Mon Sep 17 00:00:00 2001 From: Philippe Mathieu-Daudé Date: Tue, 26 Jan 2021 12:16:38 +0100 Subject: tests/qtest: Only run fuzz-virtio-scsi when virtio-scsi is available This test fails when QEMU is built without the virtio-scsi device, restrict it to its availability. Reviewed-by: Michael S. Tsirkin Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Thomas Huth Signed-off-by: Paolo Bonzini --- MAINTAINERS | 1 + tests/qtest/fuzz-test.c | 51 ------------------------- tests/qtest/fuzz-virtio-scsi-test.c | 75 +++++++++++++++++++++++++++++++++++++ tests/qtest/meson.build | 1 + 4 files changed, 77 insertions(+), 51 deletions(-) create mode 100644 tests/qtest/fuzz-virtio-scsi-test.c (limited to 'tests') diff --git a/MAINTAINERS b/MAINTAINERS index 0f560d1b91..71c835bc1d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1759,6 +1759,7 @@ S: Supported F: include/hw/scsi/* F: hw/scsi/* F: tests/qtest/virtio-scsi-test.c +F: tests/qtest/fuzz-virtio-scsi-test.c T: git https://github.com/bonzini/qemu.git scsi-next SSI diff --git a/tests/qtest/fuzz-test.c b/tests/qtest/fuzz-test.c index 631feaf0eb..00149abec7 100644 --- a/tests/qtest/fuzz-test.c +++ b/tests/qtest/fuzz-test.c @@ -24,55 +24,6 @@ static void test_lp1878642_pci_bus_get_irq_level_assert(void) qtest_quit(s); } -/* - * Here a MemoryRegionCache pointed to an MMIO region but had a - * larger size than the underlying region. - */ -static void test_mmio_oob_from_memory_region_cache(void) -{ - QTestState *s; - - s = qtest_init("-M pc-q35-5.2 -display none -m 512M " - "-device virtio-scsi,num_queues=8,addr=03.0 "); - - qtest_outl(s, 0xcf8, 0x80001811); - qtest_outb(s, 0xcfc, 0x6e); - qtest_outl(s, 0xcf8, 0x80001824); - qtest_outl(s, 0xcf8, 0x80001813); - qtest_outl(s, 0xcfc, 0xa080000); - qtest_outl(s, 0xcf8, 0x80001802); - qtest_outl(s, 0xcfc, 0x5a175a63); - qtest_outb(s, 0x6e08, 0x9e); - qtest_writeb(s, 0x9f003, 0xff); - qtest_writeb(s, 0x9f004, 0x01); - qtest_writeb(s, 0x9e012, 0x0e); - qtest_writeb(s, 0x9e01b, 0x0e); - qtest_writeb(s, 0x9f006, 0x01); - qtest_writeb(s, 0x9f008, 0x01); - qtest_writeb(s, 0x9f00a, 0x01); - qtest_writeb(s, 0x9f00c, 0x01); - qtest_writeb(s, 0x9f00e, 0x01); - qtest_writeb(s, 0x9f010, 0x01); - qtest_writeb(s, 0x9f012, 0x01); - qtest_writeb(s, 0x9f014, 0x01); - qtest_writeb(s, 0x9f016, 0x01); - qtest_writeb(s, 0x9f018, 0x01); - qtest_writeb(s, 0x9f01a, 0x01); - qtest_writeb(s, 0x9f01c, 0x01); - qtest_writeb(s, 0x9f01e, 0x01); - qtest_writeb(s, 0x9f020, 0x01); - qtest_writeb(s, 0x9f022, 0x01); - qtest_writeb(s, 0x9f024, 0x01); - qtest_writeb(s, 0x9f026, 0x01); - qtest_writeb(s, 0x9f028, 0x01); - qtest_writeb(s, 0x9f02a, 0x01); - qtest_writeb(s, 0x9f02c, 0x01); - qtest_writeb(s, 0x9f02e, 0x01); - qtest_writeb(s, 0x9f030, 0x01); - qtest_outb(s, 0x6e10, 0x00); - qtest_quit(s); -} - int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -82,8 +33,6 @@ int main(int argc, char **argv) if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { qtest_add_func("fuzz/test_lp1878642_pci_bus_get_irq_level_assert", test_lp1878642_pci_bus_get_irq_level_assert); - qtest_add_func("fuzz/test_mmio_oob_from_memory_region_cache", - test_mmio_oob_from_memory_region_cache); } return g_test_run(); diff --git a/tests/qtest/fuzz-virtio-scsi-test.c b/tests/qtest/fuzz-virtio-scsi-test.c new file mode 100644 index 0000000000..aaf6d10e18 --- /dev/null +++ b/tests/qtest/fuzz-virtio-scsi-test.c @@ -0,0 +1,75 @@ +/* + * QTest fuzzer-generated testcase for virtio-scsi device + * + * Copyright (c) 2020 Li Qiang + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" + +#include "libqos/libqtest.h" + +/* + * Here a MemoryRegionCache pointed to an MMIO region but had a + * larger size than the underlying region. + */ +static void test_mmio_oob_from_memory_region_cache(void) +{ + QTestState *s; + + s = qtest_init("-M pc-q35-5.2 -display none -m 512M " + "-device virtio-scsi,num_queues=8,addr=03.0 "); + + qtest_outl(s, 0xcf8, 0x80001811); + qtest_outb(s, 0xcfc, 0x6e); + qtest_outl(s, 0xcf8, 0x80001824); + qtest_outl(s, 0xcf8, 0x80001813); + qtest_outl(s, 0xcfc, 0xa080000); + qtest_outl(s, 0xcf8, 0x80001802); + qtest_outl(s, 0xcfc, 0x5a175a63); + qtest_outb(s, 0x6e08, 0x9e); + qtest_writeb(s, 0x9f003, 0xff); + qtest_writeb(s, 0x9f004, 0x01); + qtest_writeb(s, 0x9e012, 0x0e); + qtest_writeb(s, 0x9e01b, 0x0e); + qtest_writeb(s, 0x9f006, 0x01); + qtest_writeb(s, 0x9f008, 0x01); + qtest_writeb(s, 0x9f00a, 0x01); + qtest_writeb(s, 0x9f00c, 0x01); + qtest_writeb(s, 0x9f00e, 0x01); + qtest_writeb(s, 0x9f010, 0x01); + qtest_writeb(s, 0x9f012, 0x01); + qtest_writeb(s, 0x9f014, 0x01); + qtest_writeb(s, 0x9f016, 0x01); + qtest_writeb(s, 0x9f018, 0x01); + qtest_writeb(s, 0x9f01a, 0x01); + qtest_writeb(s, 0x9f01c, 0x01); + qtest_writeb(s, 0x9f01e, 0x01); + qtest_writeb(s, 0x9f020, 0x01); + qtest_writeb(s, 0x9f022, 0x01); + qtest_writeb(s, 0x9f024, 0x01); + qtest_writeb(s, 0x9f026, 0x01); + qtest_writeb(s, 0x9f028, 0x01); + qtest_writeb(s, 0x9f02a, 0x01); + qtest_writeb(s, 0x9f02c, 0x01); + qtest_writeb(s, 0x9f02e, 0x01); + qtest_writeb(s, 0x9f030, 0x01); + qtest_outb(s, 0x6e10, 0x00); + qtest_quit(s); +} + +int main(int argc, char **argv) +{ + const char *arch = qtest_get_arch(); + + g_test_init(&argc, &argv, NULL); + + if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { + qtest_add_func("fuzz/test_mmio_oob_from_memory_region_cache", + test_mmio_oob_from_memory_region_cache); + } + + return g_test_run(); +} diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 536991cdb8..6e871077c1 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -19,6 +19,7 @@ slow_qtests = { qtests_generic = \ (config_all_devices.has_key('CONFIG_MEGASAS_SCSI_PCI') ? ['fuzz-megasas-test'] : []) + \ + (config_all_devices.has_key('CONFIG_VIRTIO_SCSI') ? ['fuzz-virtio-scsi-test'] : []) + \ [ 'cdrom-test', 'device-introspect-test', -- cgit v1.2.3-55-g7522 From e8a2a62106d219016f8372c3888bbf555006243b Mon Sep 17 00:00:00 2001 From: Alexander Bulekov Date: Sat, 20 Feb 2021 19:47:17 -0500 Subject: fuzz: fix the pro100 generic-fuzzer config The device-type names for the pro100 network cards, are i8255.. We were matching "eepro", which catches the PCI PIO/MMIO regions for those devices, however misses the actual PCI device, which we use to map the BARs, before fuzzing. Fix that Signed-off-by: Alexander Bulekov Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Paolo Bonzini --- tests/qtest/fuzz/generic_fuzz_configs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tests') diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 5d599765c4..2454c627ff 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -177,7 +177,7 @@ const generic_fuzz_config predefined_configs[] = { .name = "i82550", .args = "-machine q35 -nodefaults " "-device i82550,netdev=net0 -netdev user,id=net0", - .objects = "eepro*" + .objects = "i8255*" },{ .name = "sdhci-v3", .args = "-nodefaults -device sdhci-pci,sd-spec-version=3 " -- cgit v1.2.3-55-g7522 From d0614b8e7a365e64ebf2ed068754787fae34d501 Mon Sep 17 00:00:00 2001 From: Alexander Bulekov Date: Wed, 10 Mar 2021 01:12:36 -0500 Subject: fuzz: don't leave orphan llvm-symbolizers around I noticed that with a sufficiently small timeout, the fuzzer fork-server sometimes locks up. On closer inspection, the issue appeared to be caused by entering our SIGALRM handler, while libfuzzer is in it's crash handlers. Because libfuzzer relies on pipe communication with an external child process to print out stack-traces, we shouldn't exit early, and leave an orphan child. Check for children in the SIGALRM handler to avoid this issue. Signed-off-by: Alexander Bulekov Acked-by: Thomas Huth Reviewed-by: Darren Kenny Signed-off-by: Paolo Bonzini --- tests/qtest/fuzz/generic_fuzz.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'tests') diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index ee8c17a04c..387ae2020a 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -583,6 +583,21 @@ static void handle_timeout(int sig) fprintf(stderr, "[Timeout]\n"); fflush(stderr); } + + /* + * If there is a crash, libfuzzer/ASAN forks a child to run an + * "llvm-symbolizer" process for printing out a pretty stacktrace. It + * communicates with this child using a pipe. If we timeout+Exit, while + * libfuzzer is still communicating with the llvm-symbolizer child, we will + * be left with an orphan llvm-symbolizer process. Sometimes, this appears + * to lead to a deadlock in the forkserver. Use waitpid to check if there + * are any waitable children. If so, exit out of the signal-handler, and + * let libfuzzer finish communicating with the child, and exit, on its own. + */ + if (waitpid(-1, NULL, WNOHANG) == 0) { + return; + } + _Exit(0); } -- cgit v1.2.3-55-g7522 From d7da0e560128e56f55a2f1f27fa66dd8c5db446c Mon Sep 17 00:00:00 2001 From: Alexander Bulekov Date: Sun, 14 Mar 2021 00:56:37 -0500 Subject: fuzz: add a am53c974 generic-fuzzer config Signed-off-by: Alexander Bulekov Reviewed-by: Darren Kenny Signed-off-by: Paolo Bonzini --- tests/qtest/fuzz/generic_fuzz_configs.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tests') diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 2454c627ff..8b8c7ac553 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -208,6 +208,12 @@ const generic_fuzz_config predefined_configs[] = { .args = "-machine q35 -nodefaults -device megasas -device scsi-cd,drive=null0 " "-blockdev driver=null-co,read-zeroes=on,node-name=null0", .objects = "megasas*", + },{ + .name = "am53c974", + .args = "-device am53c974,id=scsi -device scsi-hd,drive=disk0 " + "-drive id=disk0,if=none,file=null-co://,format=raw " + "-nodefaults", + .objects = "*esp* *scsi* *am53c974*", },{ .name = "ac97", .args = "-machine q35 -nodefaults " -- cgit v1.2.3-55-g7522 From 25d309fb0d6c07e49c3d9250cdbacc16941d988e Mon Sep 17 00:00:00 2001 From: Alexander Bulekov Date: Mon, 15 Mar 2021 10:05:11 -0400 Subject: fuzz: configure a sparse-mem device, by default The generic-fuzzer often provides randomized DMA addresses to virtual-devices. For a 64-bit address-space, the chance of these randomized addresses coinciding with RAM regions, is fairly small. Even though the fuzzer's instrumentation eventually finds valid addresses, this can take some-time, and slows-down fuzzing progress (especially, when multiple DMA buffers are involved). To work around this, create "fake" sparse-memory that spans all of the 64-bit address-space. Adjust the DMA call-back to populate this sparse memory, correspondingly Signed-off-by: Alexander Bulekov Reviewed-by: Darren Kenny Signed-off-by: Paolo Bonzini --- tests/qtest/fuzz/generic_fuzz.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'tests') diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index 387ae2020a..b5fe27aae1 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -28,6 +28,7 @@ #include "hw/pci/pci.h" #include "hw/boards.h" #include "generic_fuzz_configs.h" +#include "hw/mem/sparse-mem.h" /* * SEPARATOR is used to separate "operations" in the fuzz input @@ -64,6 +65,8 @@ static useconds_t timeout = DEFAULT_TIMEOUT_US; static bool qtest_log_enabled; +MemoryRegion *sparse_mem_mr; + /* * A pattern used to populate a DMA region or perform a memwrite. This is * useful for e.g. populating tables of unique addresses. @@ -191,8 +194,7 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr) */ if (dma_patterns->len == 0 || len == 0 - || mr != current_machine->ram - || addr > current_machine->ram_size) { + || (mr != current_machine->ram && mr != sparse_mem_mr)) { return; } @@ -238,7 +240,7 @@ void fuzz_dma_read_cb(size_t addr, size_t len, MemoryRegion *mr) MEMTXATTRS_UNSPECIFIED); if (!(memory_region_is_ram(mr1) || - memory_region_is_romd(mr1))) { + memory_region_is_romd(mr1)) && mr1 != sparse_mem_mr) { l = memory_access_size(mr1, l, addr1); } else { /* ROM/RAM case */ @@ -814,6 +816,12 @@ static void generic_pre_fuzz(QTestState *s) } qts_global = s; + /* + * Create a special device that we can use to back DMA buffers at very + * high memory addresses + */ + sparse_mem_mr = sparse_mem_init(0, UINT64_MAX); + dma_regions = g_array_new(false, false, sizeof(address_range)); dma_patterns = g_array_new(false, false, sizeof(pattern)); -- cgit v1.2.3-55-g7522