diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | include/block/aio.h | 3 | ||||
-rw-r--r-- | tests/qtest/fuzz/Makefile.include | 6 | ||||
-rw-r--r-- | tests/qtest/fuzz/i440fx_fuzz.c | 47 | ||||
-rw-r--r-- | util/aio-posix.c | 13 | ||||
-rw-r--r-- | util/aio-win32.c | 4 | ||||
-rw-r--r-- | util/async.c | 1 | ||||
-rw-r--r-- | util/fdmon-io_uring.c | 13 |
8 files changed, 69 insertions, 24 deletions
@@ -1252,7 +1252,11 @@ endif @$(if $(TARGET_DIRS), \ echo 'Architecture specific targets:'; \ $(foreach t, $(TARGET_DIRS), \ - $(call print-help-run,$(t)/all,Build for $(t));) \ + $(call print-help-run,$(t)/all,Build for $(t)); \ + $(if $(CONFIG_FUZZ), \ + $(if $(findstring softmmu,$(t)), \ + $(call print-help-run,$(t)/fuzz,Build fuzzer for $(t)); \ + ))) \ echo '') @$(if $(TOOLS), \ echo 'Tools targets:'; \ diff --git a/include/block/aio.h b/include/block/aio.h index 62ed954344..b2f703fa3f 100644 --- a/include/block/aio.h +++ b/include/block/aio.h @@ -701,6 +701,9 @@ void aio_context_setup(AioContext *ctx); */ void aio_context_destroy(AioContext *ctx); +/* Used internally, do not call outside AioContext code */ +void aio_context_use_g_source(AioContext *ctx); + /** * aio_context_set_poll_params: * @ctx: the aio context diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include index cde3e9636c..f259d866c9 100644 --- a/tests/qtest/fuzz/Makefile.include +++ b/tests/qtest/fuzz/Makefile.include @@ -7,9 +7,9 @@ fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o # Targets -fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o -fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o -fuzz-obj-y += tests/qtest/fuzz/virtio_scsi_fuzz.o +fuzz-obj-$(CONFIG_PCI_I440FX) += tests/qtest/fuzz/i440fx_fuzz.o +fuzz-obj-$(CONFIG_VIRTIO_NET) += tests/qtest/fuzz/virtio_net_fuzz.o +fuzz-obj-$(CONFIG_SCSI) += tests/qtest/fuzz/virtio_scsi_fuzz.o FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest diff --git a/tests/qtest/fuzz/i440fx_fuzz.c b/tests/qtest/fuzz/i440fx_fuzz.c index ab5f112584..bcd6769b4c 100644 --- a/tests/qtest/fuzz/i440fx_fuzz.c +++ b/tests/qtest/fuzz/i440fx_fuzz.c @@ -39,18 +39,17 @@ enum action_id { ACTION_MAX }; -static void i440fx_fuzz_qtest(QTestState *s, +static void ioport_fuzz_qtest(QTestState *s, const unsigned char *Data, size_t Size) { /* * loop over the Data, breaking it up into actions. each action has an * opcode, address offset and value */ - typedef struct QTestFuzzAction { + struct { uint8_t opcode; uint8_t addr; uint32_t value; - } QTestFuzzAction; - QTestFuzzAction a; + } a; while (Size >= sizeof(a)) { /* make a copy of the action so we can normalize the values in-place */ @@ -85,25 +84,26 @@ static void i440fx_fuzz_qtest(QTestState *s, flush_events(s); } -static void i440fx_fuzz_qos(QTestState *s, +static void i440fx_fuzz_qtest(QTestState *s, + const unsigned char *Data, + size_t Size) +{ + ioport_fuzz_qtest(s, Data, Size); +} + +static void pciconfig_fuzz_qos(QTestState *s, QPCIBus *bus, const unsigned char *Data, size_t Size) { /* - * Same as i440fx_fuzz_qtest, but using QOS. devfn is incorporated into the + * Same as ioport_fuzz_qtest, but using QOS. devfn is incorporated into the * value written over Port IO */ - typedef struct QOSFuzzAction { + struct { uint8_t opcode; uint8_t offset; int devfn; uint32_t value; - } QOSFuzzAction; - - static QPCIBus *bus; - if (!bus) { - bus = qpci_new_pc(s, fuzz_qos_alloc); - } + } a; - QOSFuzzAction a; while (Size >= sizeof(a)) { memcpy(&a, Data, sizeof(a)); switch (a.opcode % ACTION_MAX) { @@ -132,6 +132,19 @@ static void i440fx_fuzz_qos(QTestState *s, flush_events(s); } +static void i440fx_fuzz_qos(QTestState *s, + const unsigned char *Data, + size_t Size) +{ + static QPCIBus *bus; + + if (!bus) { + bus = qpci_new_pc(s, fuzz_qos_alloc); + } + + pciconfig_fuzz_qos(s, bus, Data, Size); +} + static void i440fx_fuzz_qos_fork(QTestState *s, const unsigned char *Data, size_t Size) { if (fork() == 0) { @@ -159,7 +172,7 @@ static void register_pci_fuzz_targets(void) /* Uses simple qtest commands and reboots to reset state */ fuzz_add_target(&(FuzzTarget){ .name = "i440fx-qtest-reboot-fuzz", - .description = "Fuzz the i440fx using raw qtest commands and" + .description = "Fuzz the i440fx using raw qtest commands and " "rebooting after each run", .get_init_cmdline = i440fx_argv, .fuzz = i440fx_fuzz_qtest}); @@ -167,7 +180,7 @@ static void register_pci_fuzz_targets(void) /* Uses libqos and forks to prevent state leakage */ fuzz_add_qos_target(&(FuzzTarget){ .name = "i440fx-qos-fork-fuzz", - .description = "Fuzz the i440fx using raw qtest commands and" + .description = "Fuzz the i440fx using raw qtest commands and " "rebooting after each run", .pre_vm_init = &fork_init, .fuzz = i440fx_fuzz_qos_fork,}, @@ -182,7 +195,7 @@ static void register_pci_fuzz_targets(void) */ fuzz_add_qos_target(&(FuzzTarget){ .name = "i440fx-qos-noreset-fuzz", - .description = "Fuzz the i440fx using raw qtest commands and" + .description = "Fuzz the i440fx using raw qtest commands and " "rebooting after each run", .fuzz = i440fx_fuzz_qos,}, "i440FX-pcihost", diff --git a/util/aio-posix.c b/util/aio-posix.c index c3613d299e..1b2a3af65b 100644 --- a/util/aio-posix.c +++ b/util/aio-posix.c @@ -679,6 +679,19 @@ void aio_context_destroy(AioContext *ctx) { fdmon_io_uring_destroy(ctx); fdmon_epoll_disable(ctx); + aio_free_deleted_handlers(ctx); +} + +void aio_context_use_g_source(AioContext *ctx) +{ + /* + * Disable io_uring when the glib main loop is used because it doesn't + * support mixed glib/aio_poll() usage. It relies on aio_poll() being + * called regularly so that changes to the monitored file descriptors are + * submitted, otherwise a list of pending fd handlers builds up. + */ + fdmon_io_uring_destroy(ctx); + aio_free_deleted_handlers(ctx); } void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, diff --git a/util/aio-win32.c b/util/aio-win32.c index 729d533faf..953c56ab48 100644 --- a/util/aio-win32.c +++ b/util/aio-win32.c @@ -414,6 +414,10 @@ void aio_context_destroy(AioContext *ctx) { } +void aio_context_use_g_source(AioContext *ctx) +{ +} + void aio_context_set_poll_params(AioContext *ctx, int64_t max_ns, int64_t grow, int64_t shrink, Error **errp) { diff --git a/util/async.c b/util/async.c index 3165a28f2f..1319eee3bc 100644 --- a/util/async.c +++ b/util/async.c @@ -362,6 +362,7 @@ static GSourceFuncs aio_source_funcs = { GSource *aio_get_g_source(AioContext *ctx) { + aio_context_use_g_source(ctx); g_source_ref(&ctx->source); return &ctx->source; } diff --git a/util/fdmon-io_uring.c b/util/fdmon-io_uring.c index d5a80ed6fb..1d14177df0 100644 --- a/util/fdmon-io_uring.c +++ b/util/fdmon-io_uring.c @@ -342,11 +342,18 @@ void fdmon_io_uring_destroy(AioContext *ctx) io_uring_queue_exit(&ctx->fdmon_io_uring); - /* No need to submit these anymore, just free them. */ + /* Move handlers due to be removed onto the deleted list */ while ((node = QSLIST_FIRST_RCU(&ctx->submit_list))) { + unsigned flags = atomic_fetch_and(&node->flags, + ~(FDMON_IO_URING_PENDING | + FDMON_IO_URING_ADD | + FDMON_IO_URING_REMOVE)); + + if (flags & FDMON_IO_URING_REMOVE) { + QLIST_INSERT_HEAD_RCU(&ctx->deleted_aio_handlers, node, node_deleted); + } + QSLIST_REMOVE_HEAD_RCU(&ctx->submit_list, node_submitted); - QLIST_REMOVE(node, node); - g_free(node); } ctx->fdmon_ops = &fdmon_poll_ops; |