summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--include/block/aio.h3
-rw-r--r--tests/qtest/fuzz/Makefile.include6
-rw-r--r--tests/qtest/fuzz/i440fx_fuzz.c47
-rw-r--r--util/aio-posix.c13
-rw-r--r--util/aio-win32.c4
-rw-r--r--util/async.c1
-rw-r--r--util/fdmon-io_uring.c13
8 files changed, 69 insertions, 24 deletions
diff --git a/Makefile b/Makefile
index 34275f57c9..40e4f7677b 100644
--- a/Makefile
+++ b/Makefile
@@ -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;