QEMU-Devel Archive on lore.kernel.org
 help / color / Atom feed
* [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:43   ` Paolo Bonzini
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options Oleinik, Alexander
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Using this, we avoid needing a special case to break out of main(),
early, when initializing the fuzzer, as we can just call qemu_init.
There is still a #define around main(), since it otherwise conflicts
with the libfuzzer main().

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 include/sysemu/sysemu.h |  5 +++++
 vl.c                    | 25 +++++++++++++++++++++++--
 2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 984c439ac9..a63d5ccce3 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -184,6 +184,8 @@ QemuOpts *qemu_get_machine_opts(void);
 
 bool defaults_enabled(void);
 
+int qemu_init(int argc, char **argv, char **envp);
+
 extern QemuOptsList qemu_legacy_drive_opts;
 extern QemuOptsList qemu_common_drive_opts;
 extern QemuOptsList qemu_drive_opts;
@@ -197,4 +199,7 @@ extern QemuOptsList qemu_global_opts;
 extern QemuOptsList qemu_mon_opts;
 extern QemuOptsList qemu_semihosting_config_opts;
 
+#ifdef CONFIG_FUZZ
+int real_main(int argc, char **argv, char **envp);
+#endif
 #endif
diff --git a/vl.c b/vl.c
index 130a389712..914bb9b2de 100644
--- a/vl.c
+++ b/vl.c
@@ -130,6 +130,10 @@ int main(int argc, char **argv)
 #include "sysemu/iothread.h"
 #include "qemu/guest-random.h"
 
+#ifdef CONFIG_FUZZ
+#include "tests/libqtest.h"
+#endif
+
 #define MAX_VIRTIO_CONSOLES 1
 
 static const char *data_dir[16];
@@ -2854,7 +2858,7 @@ static void user_register_global_props(void)
                       global_init_func, NULL, NULL);
 }
 
-int main(int argc, char **argv, char **envp)
+int qemu_init(int argc, char **argv, char **envp)
 {
     int i;
     int snapshot, linux_boot;
@@ -4453,7 +4457,7 @@ int main(int argc, char **argv, char **envp)
     if (vmstate_dump_file) {
         /* dump and exit */
         dump_vmstate_json_to_file(vmstate_dump_file);
-        return 0;
+        exit(0);
     }
 
     if (incoming) {
@@ -4470,6 +4474,23 @@ int main(int argc, char **argv, char **envp)
     accel_setup_post(current_machine);
     os_setup_post();
 
+    return 0;
+}
+#ifdef CONFIG_FUZZ
+/*
+ * Without this, the compiler complains about all of the unused
+ * cleanup and shutdown() functions
+ */
+int real_main(int argc, char **argv, char **envp)
+#else
+int main(int argc, char **argv, char **envp)
+#endif
+{
+    int ret = qemu_init(argc, argv, envp);
+    if (ret != 0) {
+        return ret;
+    }
+
     main_loop();
 
     gdbserver_cleanup();
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support
@ 2019-08-05  7:11 Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init Oleinik, Alexander
                   ` (17 more replies)
  0 siblings, 18 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Changes since v1
 * Split off changes to qos virtio-net and qtest server to other patches
 * Move vl:main initialization into new func: qemu_init
 * Moved useful functions from qos-test.c to a separate object
 * Use struct of function pointers for add_fuzz_target(), instead of
   arguments
 * Move ramfile to migration/qemu-file
 * Rewrite fork-based fuzzer pending patch to libfuzzer
 * Pass check-patch

Based-on: 20190805032400.8054-1-alxndr@bu.edu
Based-on: 20190805031240.6024-1-alxndr@bu.edu

---
As part of Google Summer of Code 2019, I'm working on integrating
fuzzing of virtual devices into QEMU [1]. This is a highly WIP patchset
adding this functionality.

Fuzzers provide random data to a program and monitor its execution for
errors. Coverage-guided fuzzers also observe the parts of the program
that are exercised by each input, and use this information to
mutate/guide the inputs to reach additional parts of the program. They
are quite effective for finding bugs in a wide range of software. 

Summary:
 - The virtual-device fuzzers use libfuzzer [2] for coverage-guided
   in-process fuzzing.
 - To fuzz a device, create a new fuzz "target" - i.e. a function that
   exercises QEMU based on inputs provided by the fuzzer.
 - Fuzz targets rely on qtest and libqos to turn inputs into actions.
 - Since libfuzzer does in-process fuzzing, the QEMU state needs to be
   reset after each fuzz run. These patches provide three methods for
   resetting state.
 - There are currently few targets, but they have already helped
   discover bugs in the console, and virtio-net, and have reproduced
   previously-reported vulnerabilities.

Alexander Oleinik (17):
  fuzz: Move initialization from main to qemu_init
  fuzz: Add fuzzer configure options
  fuzz: Keep memory mapped for fork-based fuzzer
  fuzz: Skip modules that were already initialized
  fuzz: Add direct receive function for qtest server
  fuzz: Add FUZZ_TARGET module type
  fuzz: Add ramfile qemu-file type
  fuzz: Export the qemu_savevm_live_state function
  fuzz: hardcode needed objects into i386 target
  fuzz: qtest client directly interacts with server
  fuzz: Move useful qos functions to separate object
  fuzz: Add fuzzer skeleton
  fuzz: Add libqos support to the fuzzer
  fuzz: Add forking support to the fuzzer
  fuzz: Add general qtest fuzz-target
  fuzz: Add virtio-net fuzz targets
  fuzz: Add fuzz accelerator type

 accel/fuzz.c                 |  48 +++++++
 configure                    |  15 ++
 exec.c                       |   2 +
 include/qemu/module.h        |   4 +-
 include/sysemu/fuzz.h        |  15 ++
 include/sysemu/qtest.h       |   4 +
 include/sysemu/sysemu.h      |   5 +
 migration/qemu-file.c        |  84 +++++++++++
 migration/qemu-file.h        |  11 ++
 migration/savevm.c           |   9 +-
 migration/savevm.h           |   2 +
 qtest.c                      |  14 ++
 target/i386/Makefile.objs    |  20 +++
 tests/fuzz/fuzz.c            | 245 +++++++++++++++++++++++++++++++++
 tests/fuzz/fuzz.h            |  70 ++++++++++
 tests/fuzz/fuzzer_hooks.c    |  62 +++++++++
 tests/fuzz/fuzzer_hooks.h    |  21 +++
 tests/fuzz/qos_fuzz.c        |  58 ++++++++
 tests/fuzz/qos_fuzz.h        |  23 ++++
 tests/fuzz/qos_helpers.c     | 190 +++++++++++++++++++++++++
 tests/fuzz/qos_helpers.h     |  17 +++
 tests/fuzz/qtest_fuzz.c      | 260 +++++++++++++++++++++++++++++++++++
 tests/fuzz/qtest_fuzz.h      |  37 +++++
 tests/fuzz/virtio-net-fuzz.c | 254 ++++++++++++++++++++++++++++++++++
 tests/libqos/qos_external.c  | 149 ++++++++++++++++++++
 tests/libqos/qos_external.h  |   8 ++
 tests/libqtest.c             |  61 +++++++-
 tests/libqtest.h             |   6 +
 tests/qos-test.c             | 132 +-----------------
 util/module.c                |   7 +
 vl.c                         |  25 +++-
 31 files changed, 1720 insertions(+), 138 deletions(-)
 create mode 100644 accel/fuzz.c
 create mode 100644 include/sysemu/fuzz.h
 create mode 100644 tests/fuzz/fuzz.c
 create mode 100644 tests/fuzz/fuzz.h
 create mode 100644 tests/fuzz/fuzzer_hooks.c
 create mode 100644 tests/fuzz/fuzzer_hooks.h
 create mode 100644 tests/fuzz/qos_fuzz.c
 create mode 100644 tests/fuzz/qos_fuzz.h
 create mode 100644 tests/fuzz/qos_helpers.c
 create mode 100644 tests/fuzz/qos_helpers.h
 create mode 100644 tests/fuzz/qtest_fuzz.c
 create mode 100644 tests/fuzz/qtest_fuzz.h
 create mode 100644 tests/fuzz/virtio-net-fuzz.c
 create mode 100644 tests/libqos/qos_external.c
 create mode 100644 tests/libqos/qos_external.h

-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:44   ` Paolo Bonzini
  2019-08-12 22:39   ` Bandan Das
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 03/17] fuzz: Keep memory mapped for fork-based fuzzer Oleinik, Alexander
                   ` (15 subsequent siblings)
  17 siblings, 2 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

This adds sanitizer/fuzzer related cflags and adds tests/ to the include
path. This include change is needed for qos to build, and is normally
located in tests/Makefile.include, but currently the fuzzer builds from
the i386-softmmu target, not anything in tests.

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 configure | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/configure b/configure
index 714e7fb6a1..69ef1e7c7d 100755
--- a/configure
+++ b/configure
@@ -499,6 +499,7 @@ docker="no"
 debug_mutex="no"
 libpmem=""
 default_devices="yes"
+fuzzing="no"
 
 # cross compilers defaults, can be overridden with --cross-cc-ARCH
 cross_cc_aarch64="aarch64-linux-gnu-gcc"
@@ -1543,6 +1544,8 @@ for opt do
   ;;
   --disable-libpmem) libpmem=no
   ;;
+  --enable-fuzzing) fuzzing=yes
+  ;;
   *)
       echo "ERROR: unknown option $opt"
       echo "Try '$0 --help' for more information"
@@ -6481,6 +6484,7 @@ echo "docker            $docker"
 echo "libpmem support   $libpmem"
 echo "libudev           $libudev"
 echo "default devices   $default_devices"
+echo "fuzzing support   $fuzzing"
 
 if test "$supported_cpu" = "no"; then
     echo
@@ -7306,6 +7310,17 @@ fi
 if test "$sheepdog" = "yes" ; then
   echo "CONFIG_SHEEPDOG=y" >> $config_host_mak
 fi
+if test "$fuzzing" = "yes" ; then
+  QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize=fuzzer,address  -fprofile-instr-generate"
+  QEMU_CFLAGS="$QEMU_CFLAGS -fprofile-instr-generate -fcoverage-mapping"
+  QEMU_LDFLAGS="$LDFLAGS -fsanitize=fuzzer,address"
+
+  # Add tests/ to include path, since this is done in tests/Makefile.include,
+  # and required for QOS objects to build. This can be removed if/when the
+  # fuzzer is compiled using rules in tests/Makefile.include
+  QEMU_INCLUDES="-iquote \$(SRC_PATH)/tests $QEMU_INCLUDES"
+  echo "CONFIG_FUZZ=y" >> $config_host_mak
+fi
 
 if test "$tcg_interpreter" = "yes"; then
   QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 03/17] fuzz: Keep memory mapped for fork-based fuzzer
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-09  9:01   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized Oleinik, Alexander
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: pbonzini, bsd, Richard Henderson, stefanha, Oleinik,  Alexander

Otherwise, the RAM is unmapped from the child-processes, which breaks
any fuzz tests relying on DMA.

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 exec.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/exec.c b/exec.c
index 3e78de3b8f..b3b56db8f0 100644
--- a/exec.c
+++ b/exec.c
@@ -2317,7 +2317,9 @@ static void ram_block_add(RAMBlock *new_block, Error **errp, bool shared)
         qemu_ram_setup_dump(new_block->host, new_block->max_length);
         qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_HUGEPAGE);
         /* MADV_DONTFORK is also needed by KVM in absence of synchronous MMU */
+#ifndef CONFIG_FUZZ /* This conflicts with fork-based fuzzing */
         qemu_madvise(new_block->host, new_block->max_length, QEMU_MADV_DONTFORK);
+#endif
         ram_block_notify_add(new_block->host, new_block->max_length);
     }
 }
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (2 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 03/17] fuzz: Keep memory mapped for fork-based fuzzer Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:44   ` Paolo Bonzini
  2019-08-09  9:04   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 05/17] fuzz: Add direct receive function for qtest server Oleinik, Alexander
                   ` (13 subsequent siblings)
  17 siblings, 2 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 util/module.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/util/module.c b/util/module.c
index 142db7e911..3d4380fd47 100644
--- a/util/module.c
+++ b/util/module.c
@@ -30,6 +30,7 @@ typedef struct ModuleEntry
 typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
 
 static ModuleTypeList init_type_list[MODULE_INIT_MAX];
+static bool modules_init_done[MODULE_INIT_MAX];
 
 static ModuleTypeList dso_init_list;
 
@@ -91,11 +92,17 @@ void module_call_init(module_init_type type)
     ModuleTypeList *l;
     ModuleEntry *e;
 
+    if (modules_init_done[type]) {
+        return;
+    }
+
     l = find_type(type);
 
     QTAILQ_FOREACH(e, l, node) {
         e->init();
     }
+
+    modules_init_done[type] = true;
 }
 
 #ifdef CONFIG_MODULES
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 05/17] fuzz: Add direct receive function for qtest server
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (3 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-09  9:23   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 06/17] fuzz: Add FUZZ_TARGET module type Oleinik, Alexander
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Thomas Huth, Oleinik, Alexander, bsd, stefanha, pbonzini

The direct receive function qtest_server_recv is directly invoked by the
qtest client, when the server and client exist within the same process.

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 include/sysemu/qtest.h |  4 ++++
 qtest.c                | 14 ++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h
index 5ed09c80b1..a7b7a3081e 100644
--- a/include/sysemu/qtest.h
+++ b/include/sysemu/qtest.h
@@ -26,4 +26,8 @@ bool qtest_driver(void);
 
 void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
 
+#ifdef CONFIG_FUZZ
+void qtest_server_recv(GString *inbuf); /* Client sends commands using this */
+#endif
+
 #endif
diff --git a/qtest.c b/qtest.c
index c9681dbdf3..427e1e5076 100644
--- a/qtest.c
+++ b/qtest.c
@@ -31,6 +31,9 @@
 #ifdef TARGET_PPC64
 #include "hw/ppc/spapr_rtas.h"
 #endif
+#ifdef CONFIG_FUZZ
+#include "tests/libqtest.h"
+#endif
 
 #define MAX_IRQ 256
 
@@ -231,10 +234,14 @@ static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char *fmt, ...)
 
 static void do_qtest_send(CharBackend *chr, const char *str, size_t len)
 {
+#ifdef CONFIG_FUZZ
+    qtest_client_recv(str, len);
+#else
     qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
     if (qtest_log_fp && qtest_opened) {
         fprintf(qtest_log_fp, "%s", str);
     }
+#endif
 }
 
 static void qtest_send(CharBackend *chr, const char *str)
@@ -760,6 +767,7 @@ void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **
         return;
     }
 
+    assert(!qtest_log_fp);
     if (qtest_log) {
         if (strcmp(qtest_log, "none") != 0) {
             qtest_log_fp = fopen(qtest_log, "w+");
@@ -780,3 +788,9 @@ bool qtest_driver(void)
 {
     return qtest_chr.chr != NULL;
 }
+#ifdef CONFIG_FUZZ
+void qtest_server_recv(GString *inbuf)
+{
+    qtest_process_inbuf(NULL, inbuf);
+}
+#endif
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 06/17] fuzz: Add FUZZ_TARGET module type
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (4 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 05/17] fuzz: Add direct receive function for qtest server Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-09  9:07   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type Oleinik, Alexander
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 include/qemu/module.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/include/qemu/module.h b/include/qemu/module.h
index db3065381d..cb37ef647e 100644
--- a/include/qemu/module.h
+++ b/include/qemu/module.h
@@ -46,6 +46,7 @@ typedef enum {
     MODULE_INIT_TRACE,
     MODULE_INIT_XEN_BACKEND,
     MODULE_INIT_LIBQOS,
+    MODULE_INIT_FUZZ_TARGET,
     MODULE_INIT_MAX
 } module_init_type;
 
@@ -56,7 +57,8 @@ typedef enum {
 #define xen_backend_init(function) module_init(function, \
                                                MODULE_INIT_XEN_BACKEND)
 #define libqos_init(function) module_init(function, MODULE_INIT_LIBQOS)
-
+#define fuzz_target_init(function) module_init(function, \
+                                               MODULE_INIT_FUZZ_TARGET)
 #define block_module_load_one(lib) module_load_one("block-", lib)
 #define ui_module_load_one(lib) module_load_one("ui-", lib)
 #define audio_module_load_one(lib) module_load_one("audio-", lib)
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (5 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 06/17] fuzz: Add FUZZ_TARGET module type Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:50   ` Paolo Bonzini
  2019-08-05 10:46   ` Dr. David Alan Gilbert
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 08/17] fuzz: Export the qemu_savevm_live_state function Oleinik, Alexander
                   ` (10 subsequent siblings)
  17 siblings, 2 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Juan Quintela, Dr. David Alan Gilbert, Oleinik, Alexander, bsd,
	stefanha, pbonzini

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 migration/qemu-file.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 migration/qemu-file.h | 11 ++++++
 2 files changed, 95 insertions(+)

diff --git a/migration/qemu-file.c b/migration/qemu-file.c
index 0431585502..453e2897d5 100644
--- a/migration/qemu-file.c
+++ b/migration/qemu-file.c
@@ -786,3 +786,87 @@ void qemu_file_set_blocking(QEMUFile *f, bool block)
         f->ops->set_blocking(f->opaque, block);
     }
 }
+
+#ifdef CONFIG_FUZZ
+#define INCREMENT 10240
+static ssize_t ram_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
+        int64_t pos)
+{
+    ram_disk *rd = (ram_disk *)opaque;
+    gsize newsize;
+    ssize_t total_size = 0;
+    int i;
+    if (!rd->base) {
+        rd->base = g_malloc(INCREMENT);
+        rd->len = INCREMENT;
+    }
+    for (i = 0; i < iovcnt; i++) {
+        if (pos + iov[i].iov_len >= rd->len) {
+            newsize = ((pos + iov[i].iov_len) / INCREMENT + 1) * INCREMENT;
+            rd->base = g_realloc(rd->base, newsize);
+            rd->len = newsize;
+        }
+        memcpy(rd->base + pos, iov[i].iov_base, iov[i].iov_len);
+        pos += iov[i].iov_len;
+        total_size += iov[i].iov_len;
+    }
+    return total_size;
+}
+
+static ssize_t ram_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
+        size_t size)
+{
+    ram_disk *rd = (ram_disk *)opaque;
+    if (pos + size > rd->len) {
+        if (rd->len - pos >= 0) {
+            memcpy(buf, rd->base + pos, rd->len - pos);
+            size = rd->len - pos;
+        }
+    } else {
+        memcpy(buf, rd->base + pos, size);
+    }
+    return size;
+}
+
+static int ram_fclose(void *opaque)
+{
+    return 0;
+}
+
+static const QEMUFileOps ram_read_ops = {
+    .get_buffer = ram_get_buffer,
+    .close =      ram_fclose
+};
+
+static const QEMUFileOps ram_write_ops = {
+    .writev_buffer = ram_writev_buffer,
+    .close =      ram_fclose
+};
+
+QEMUFile *qemu_fopen_ram(ram_disk **return_rd)
+{
+    ram_disk *rd = g_new0(ram_disk, 1);
+    *return_rd = rd;
+    return qemu_fopen_ops(rd, &ram_write_ops);
+}
+
+QEMUFile *qemu_fopen_ro_ram(ram_disk* rd)
+{
+    return qemu_fopen_ops(rd, &ram_read_ops);
+}
+
+void qemu_freopen_ro_ram(QEMUFile *f)
+{
+    void *rd = f->opaque;
+    f->bytes_xfer = 0;
+    f->xfer_limit = 0;
+    f->last_error = 0;
+    f->iovcnt = 0;
+    f->buf_index = 0;
+    f->buf_size = 0;
+    f->pos = 0;
+    f->ops = &ram_read_ops;
+    f->opaque = rd;
+    return;
+}
+#endif
diff --git a/migration/qemu-file.h b/migration/qemu-file.h
index 13baf896bd..7048674f1b 100644
--- a/migration/qemu-file.h
+++ b/migration/qemu-file.h
@@ -177,4 +177,15 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
 
 void qemu_put_counted_string(QEMUFile *f, const char *name);
 
+#ifdef CONFIG_FUZZ
+typedef struct ram_disk {
+    void *base;
+    gsize len;
+} ram_disk;
+
+QEMUFile *qemu_fopen_ram(ram_disk **rd);
+QEMUFile *qemu_fopen_ro_ram(ram_disk* rd);
+void qemu_freopen_ro_ram(QEMUFile *f);
+#endif
+
 #endif
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 08/17] fuzz: Export the qemu_savevm_live_state function
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (6 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05 10:54   ` Dr. David Alan Gilbert
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 09/17] fuzz: hardcode needed objects into i386 target Oleinik, Alexander
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Juan Quintela, Dr. David Alan Gilbert, Oleinik, Alexander, bsd,
	stefanha, pbonzini

Skip the header when saving device state, as the header isn't handled by
qemu_load_device_state

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 migration/savevm.c | 9 +++++++--
 migration/savevm.h | 2 ++
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/migration/savevm.c b/migration/savevm.c
index 79ed44d475..5eac36e6ca 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -1405,7 +1405,7 @@ void qemu_savevm_state_cleanup(void)
     }
 }
 
-static int qemu_savevm_state(QEMUFile *f, Error **errp)
+int qemu_savevm_state(QEMUFile *f, Error **errp)
 {
     int ret;
     MigrationState *ms = migrate_get_current();
@@ -1471,11 +1471,16 @@ void qemu_savevm_live_state(QEMUFile *f)
 int qemu_save_device_state(QEMUFile *f)
 {
     SaveStateEntry *se;
-
+    /*
+     * qemu_load_device_state doesn't load the header. Either skip writing the
+     * header or seek forward in the file, prior to loading device state
+     */
+#ifndef CONFIG_FUZZ
     if (!migration_in_colo_state()) {
         qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
         qemu_put_be32(f, QEMU_VM_FILE_VERSION);
     }
+#endif
     cpu_synchronize_all_states();
 
     QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
diff --git a/migration/savevm.h b/migration/savevm.h
index 51a4b9caa8..5405215cb4 100644
--- a/migration/savevm.h
+++ b/migration/savevm.h
@@ -64,4 +64,6 @@ void qemu_loadvm_state_cleanup(void);
 int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis);
 int qemu_load_device_state(QEMUFile *f);
 
+int qemu_savevm_state(QEMUFile *f, Error **errp);
+
 #endif
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 09/17] fuzz: hardcode needed objects into i386 target
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (7 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 08/17] fuzz: Export the qemu_savevm_live_state function Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-09  9:33   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 10/17] fuzz: qtest client directly interacts with server Oleinik, Alexander
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eduardo Habkost, Oleinik, Alexander, bsd, stefanha, pbonzini,
	Richard Henderson

Temporary solution until there is a better build solution for fuzzers in
tests/Makefile.include

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 target/i386/Makefile.objs | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs
index 48e0c28434..1b8976c0a6 100644
--- a/target/i386/Makefile.objs
+++ b/target/i386/Makefile.objs
@@ -18,5 +18,25 @@ endif
 obj-$(CONFIG_HVF) += hvf/
 obj-$(CONFIG_WHPX) += whpx-all.o
 endif
+
+# Need to link against target, qtest and qos.. Just list everything here, until
+# I find a better way to integrate into the build system
+ifeq ($(CONFIG_FUZZ),y)
+obj-$(CONFIG_FUZZ) += ../../accel/fuzz.o ../../tests/libqos/qos_external.o
+obj-$(CONFIG_FUZZ) += ../../tests/fuzz/fuzz.o ../../tests/fuzz/fuzzer_hooks.o
+obj-$(CONFIG_FUZZ) += ../../tests/fuzz/virtio-net-fuzz.o
+obj-$(CONFIG_FUZZ) += ../../tests/fuzz/snapshotting.o
+obj-$(CONFIG_FUZZ) += ../../tests/fuzz/qtest_fuzz.o
+obj-$(CONFIG_FUZZ) += ../../tests/libqtest.o
+obj-$(CONFIG_FUZZ) += ../../tests/libqos/qgraph.o ../../tests/libqos/libqos.o
+obj-$(CONFIG_FUZZ) += ../../tests/fuzz/qos_fuzz.o ../../tests/fuzz/qos_helpers.o
+obj-$(CONFIG_FUZZ) +=  ../../tests/libqos/malloc.o ../../tests/libqos/pci-pc.o \
+	../../tests/libqos/virtio-pci.o ../../tests/libqos/malloc-pc.o \
+	../../tests/libqos/libqos-pc.o ../../tests/libqos/fw_cfg.o \
+	../../tests/libqos/e1000e.o ../../tests/libqos/pci.o \
+	../../tests/libqos/pci-pc.o ../../tests/libqos/virtio.o \
+	../../tests/libqos/virtio-net.o ../../tests/libqos/x86_64_pc-machine.o
+endif
+
 obj-$(CONFIG_SEV) += sev.o
 obj-$(call lnot,$(CONFIG_SEV)) += sev-stub.o
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 10/17] fuzz: qtest client directly interacts with server
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (8 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 09/17] fuzz: hardcode needed objects into i386 target Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-09  9:37   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 11/17] fuzz: Move useful qos functions to separate object Oleinik, Alexander
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Thomas Huth, Oleinik, Alexander, bsd, stefanha, pbonzini

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/libqtest.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++--
 tests/libqtest.h |  6 +++++
 2 files changed, 65 insertions(+), 2 deletions(-)

diff --git a/tests/libqtest.c b/tests/libqtest.c
index 3c5c3f49d8..a9c1dc4fb6 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -30,12 +30,18 @@
 #include "qapi/qmp/qjson.h"
 #include "qapi/qmp/qlist.h"
 #include "qapi/qmp/qstring.h"
+#ifdef CONFIG_FUZZ
+#include "sysemu/qtest.h"
+#endif
 
 #define MAX_IRQ 256
 #define SOCKET_TIMEOUT 50
 #define SOCKET_MAX_FDS 16
 
 QTestState *global_qtest;
+#ifdef CONFIG_FUZZ
+static GString *recv_str;
+#endif
 
 struct QTestState
 {
@@ -317,6 +323,21 @@ QTestState *qtest_initf(const char *fmt, ...)
     return s;
 }
 
+#ifdef CONFIG_FUZZ
+QTestState *qtest_fuzz_init(const char *extra_args, int *sock_fd)
+{
+    QTestState *qts;
+    qts = g_new(QTestState, 1);
+    qts->wstatus = 0;
+    for (int i = 0; i < MAX_IRQ; i++) {
+        qts->irq_level[i] = false;
+    }
+    qts->big_endian = qtest_query_target_endianness(qts);
+
+    return qts;
+}
+#endif
+
 QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd)
 {
     int sock_fd_init;
@@ -374,14 +395,25 @@ static void socket_send(int fd, const char *buf, size_t size)
         offset += len;
     }
 }
-
+/*
+ * TODO: Remove the ifdefs by adding a layer of indirection and separating the
+ * implemetation of sendf and init for the fuzzer and qtest client
+ */
 static void socket_sendf(int fd, const char *fmt, va_list ap)
 {
     gchar *str = g_strdup_vprintf(fmt, ap);
     size_t size = strlen(str);
+#ifdef CONFIG_FUZZ
+    /* Directly call qtest_process_inbuf in the qtest server */
+    GString *gstr = g_string_new_len(str, size);
+    qtest_server_recv(gstr);
 
+    g_string_free(gstr, true);
+    g_free(str);
+#else
     socket_send(fd, str, size);
     g_free(str);
+#endif
 }
 
 static void GCC_FMT_ATTR(2, 3) qtest_sendf(QTestState *s, const char *fmt, ...)
@@ -433,6 +465,13 @@ static GString *qtest_recv_line(QTestState *s)
     size_t offset;
     char *eol;
 
+#ifdef CONFIG_FUZZ
+    eol = strchr(recv_str->str, '\n');
+    offset = eol - recv_str->str;
+    line = g_string_new_len(recv_str->str, offset);
+    g_string_erase(recv_str, 0, offset + 1);
+    printf("<<< %s\n", line->str);
+#else
     while ((eol = strchr(s->rx->str, '\n')) == NULL) {
         ssize_t len;
         char buffer[1024];
@@ -453,7 +492,7 @@ static GString *qtest_recv_line(QTestState *s)
     offset = eol - s->rx->str;
     line = g_string_new_len(s->rx->str, offset);
     g_string_erase(s->rx, 0, offset + 1);
-
+#endif
     return line;
 }
 
@@ -797,6 +836,9 @@ char *qtest_hmp(QTestState *s, const char *fmt, ...)
 
 const char *qtest_get_arch(void)
 {
+#ifdef CONFIG_FUZZ
+    return TARGET_NAME;
+#endif
     const char *qemu = qtest_qemu_binary();
     const char *end = strrchr(qemu, '/');
 
@@ -1339,3 +1381,18 @@ void qmp_assert_error_class(QDict *rsp, const char *class)
 
     qobject_unref(rsp);
 }
+#ifdef CONFIG_FUZZ
+void qtest_clear_rxbuf(QTestState *s)
+{
+    g_string_set_size(recv_str, 0);
+}
+
+void qtest_client_recv(const char *str, size_t len)
+{
+    if (!recv_str) {
+        recv_str = g_string_new(NULL);
+    }
+    g_string_append_len(recv_str, str, len);
+    return;
+}
+#endif
diff --git a/tests/libqtest.h b/tests/libqtest.h
index cadf1d4a03..4e32f39be7 100644
--- a/tests/libqtest.h
+++ b/tests/libqtest.h
@@ -1001,4 +1001,10 @@ void qmp_assert_error_class(QDict *rsp, const char *class);
  */
 bool qtest_probe_child(QTestState *s);
 
+#ifdef CONFIG_FUZZ
+QTestState *qtest_fuzz_init(const char *extra_args, int *sock_fd);
+void qtest_clear_rxbuf(QTestState *s);
+void qtest_client_recv(const char *str, size_t len);
+#endif
+
 #endif
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 11/17] fuzz: Move useful qos functions to separate object
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (9 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 10/17] fuzz: qtest client directly interacts with server Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 12/17] fuzz: Add fuzzer skeleton Oleinik, Alexander
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel
  Cc: Laurent Vivier, Thomas Huth, Oleinik, Alexander, bsd, stefanha, pbonzini

These functions are used by both qos-test.c, and the fuzzer.

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/libqos/qos_external.c | 149 ++++++++++++++++++++++++++++++++++++
 tests/libqos/qos_external.h |   8 ++
 tests/qos-test.c            | 132 +-------------------------------
 3 files changed, 158 insertions(+), 131 deletions(-)
 create mode 100644 tests/libqos/qos_external.c
 create mode 100644 tests/libqos/qos_external.h

diff --git a/tests/libqos/qos_external.c b/tests/libqos/qos_external.c
new file mode 100644
index 0000000000..987123b5cb
--- /dev/null
+++ b/tests/libqos/qos_external.c
@@ -0,0 +1,149 @@
+
+#include "qemu/osdep.h"
+#include <getopt.h>
+#include "libqtest.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qstring.h"
+#include "qemu/module.h"
+#include "qapi/qmp/qlist.h"
+#include "libqos/malloc.h"
+#include "libqos/qgraph.h"
+#include "libqos/qgraph_internal.h"
+#include "libqos/qos_external.h"
+
+void apply_to_node(const char *name, bool is_machine, bool is_abstract)
+{
+    char *machine_name = NULL;
+    if (is_machine) {
+        const char *arch = qtest_get_arch();
+        machine_name = g_strconcat(arch, "/", name, NULL);
+        name = machine_name;
+    }
+    qos_graph_node_set_availability(name, true);
+    if (is_abstract) {
+        qos_delete_cmd_line(name);
+    }
+    g_free(machine_name);
+}
+
+/**
+ * apply_to_qlist(): using QMP queries QEMU for a list of
+ * machines and devices available, and sets the respective node
+ * as true. If a node is found, also all its produced and contained
+ * child are marked available.
+ *
+ * See qos_graph_node_set_availability() for more info
+ */
+void apply_to_qlist(QList *list, bool is_machine)
+{
+    const QListEntry *p;
+    const char *name;
+    bool abstract;
+    QDict *minfo;
+    QObject *qobj;
+    QString *qstr;
+    QBool *qbool;
+
+    for (p = qlist_first(list); p; p = qlist_next(p)) {
+        minfo = qobject_to(QDict, qlist_entry_obj(p));
+        qobj = qdict_get(minfo, "name");
+        qstr = qobject_to(QString, qobj);
+        name = qstring_get_str(qstr);
+
+        qobj = qdict_get(minfo, "abstract");
+        if (qobj) {
+            qbool = qobject_to(QBool, qobj);
+            abstract = qbool_get_bool(qbool);
+        } else {
+            abstract = false;
+        }
+
+        apply_to_node(name, is_machine, abstract);
+        qobj = qdict_get(minfo, "alias");
+        if (qobj) {
+            qstr = qobject_to(QString, qobj);
+            name = qstring_get_str(qstr);
+            apply_to_node(name, is_machine, abstract);
+        }
+    }
+}
+
+QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
+{
+    return obj->get_driver(obj, "memory");
+}
+
+/**
+ * allocate_objects(): given an array of nodes @arg,
+ * walks the path invoking all constructors and
+ * passing the corresponding parameter in order to
+ * continue the objects allocation.
+ * Once the test is reached, return the object it consumes.
+ *
+ * Since the machine and QEDGE_CONSUMED_BY nodes allocate
+ * memory in the constructor, g_test_queue_destroy is used so
+ * that after execution they can be safely free'd.  (The test's
+ * ->before callback is also welcome to use g_test_queue_destroy).
+ *
+ * Note: as specified in walk_path() too, @arg is an array of
+ * char *, where arg[0] is a pointer to the command line
+ * string that will be used to properly start QEMU when executing
+ * the test, and the remaining elements represent the actual objects
+ * that will be allocated.
+ */
+void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc)
+{
+    int current = 0;
+    QGuestAllocator *alloc;
+    QOSGraphObject *parent = NULL;
+    QOSGraphEdge *edge;
+    QOSGraphNode *node;
+    void *edge_arg;
+    void *obj;
+
+    node = qos_graph_get_node(path[current]);
+    g_assert(node->type == QNODE_MACHINE);
+
+    obj = qos_machine_new(node, qts);
+    qos_object_queue_destroy(obj);
+
+    alloc = get_machine_allocator(obj);
+    if (p_alloc) {
+        *p_alloc = alloc;
+    }
+
+    for (;;) {
+        if (node->type != QNODE_INTERFACE) {
+            qos_object_start_hw(obj);
+            parent = obj;
+        }
+
+        /* follow edge and get object for next node constructor */
+        current++;
+        edge = qos_graph_get_edge(path[current - 1], path[current]);
+        node = qos_graph_get_node(path[current]);
+
+        if (node->type == QNODE_TEST) {
+            g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY);
+            return obj;
+        }
+
+        switch (qos_graph_edge_get_type(edge)) {
+        case QEDGE_PRODUCES:
+            obj = parent->get_driver(parent, path[current]);
+            break;
+
+        case QEDGE_CONSUMED_BY:
+            edge_arg = qos_graph_edge_get_arg(edge);
+            obj = qos_driver_new(node, obj, alloc, edge_arg);
+            qos_object_queue_destroy(obj);
+            break;
+
+        case QEDGE_CONTAINS:
+            obj = parent->get_device(parent, path[current]);
+            break;
+        }
+    }
+}
+
diff --git a/tests/libqos/qos_external.h b/tests/libqos/qos_external.h
new file mode 100644
index 0000000000..bf3b308501
--- /dev/null
+++ b/tests/libqos/qos_external.h
@@ -0,0 +1,8 @@
+#ifndef QOS_EXTERNAL_H
+#define QOS_EXTERNAL_H
+
+void apply_to_node(const char *name, bool is_machine, bool is_abstract);
+void apply_to_qlist(QList *list, bool is_machine);
+QGuestAllocator *get_machine_allocator(QOSGraphObject *obj);
+void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc);
+#endif
diff --git a/tests/qos-test.c b/tests/qos-test.c
index 3c0071b3b7..c5fa7ff586 100644
--- a/tests/qos-test.c
+++ b/tests/qos-test.c
@@ -27,65 +27,11 @@
 #include "libqos/malloc.h"
 #include "libqos/qgraph.h"
 #include "libqos/qgraph_internal.h"
+#include "libqos/qos_external.h"
 
 static char *old_path;
 
-static void apply_to_node(const char *name, bool is_machine, bool is_abstract)
-{
-    char *machine_name = NULL;
-    if (is_machine) {
-        const char *arch = qtest_get_arch();
-        machine_name = g_strconcat(arch, "/", name, NULL);
-        name = machine_name;
-    }
-    qos_graph_node_set_availability(name, true);
-    if (is_abstract) {
-        qos_delete_cmd_line(name);
-    }
-    g_free(machine_name);
-}
 
-/**
- * apply_to_qlist(): using QMP queries QEMU for a list of
- * machines and devices available, and sets the respective node
- * as true. If a node is found, also all its produced and contained
- * child are marked available.
- *
- * See qos_graph_node_set_availability() for more info
- */
-static void apply_to_qlist(QList *list, bool is_machine)
-{
-    const QListEntry *p;
-    const char *name;
-    bool abstract;
-    QDict *minfo;
-    QObject *qobj;
-    QString *qstr;
-    QBool *qbool;
-
-    for (p = qlist_first(list); p; p = qlist_next(p)) {
-        minfo = qobject_to(QDict, qlist_entry_obj(p));
-        qobj = qdict_get(minfo, "name");
-        qstr = qobject_to(QString, qobj);
-        name = qstring_get_str(qstr);
-
-        qobj = qdict_get(minfo, "abstract");
-        if (qobj) {
-            qbool = qobject_to(QBool, qobj);
-            abstract = qbool_get_bool(qbool);
-        } else {
-            abstract = false;
-        }
-
-        apply_to_node(name, is_machine, abstract);
-        qobj = qdict_get(minfo, "alias");
-        if (qobj) {
-            qstr = qobject_to(QString, qobj);
-            name = qstring_get_str(qstr);
-            apply_to_node(name, is_machine, abstract);
-        }
-    }
-}
 
 /**
  * qos_set_machines_devices_available(): sets availability of qgraph
@@ -129,10 +75,6 @@ static void qos_set_machines_devices_available(void)
     qobject_unref(response);
 }
 
-static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
-{
-    return obj->get_driver(obj, "memory");
-}
 
 static void restart_qemu_or_continue(char *path)
 {
@@ -159,78 +101,6 @@ void qos_invalidate_command_line(void)
     old_path = NULL;
 }
 
-/**
- * allocate_objects(): given an array of nodes @arg,
- * walks the path invoking all constructors and
- * passing the corresponding parameter in order to
- * continue the objects allocation.
- * Once the test is reached, return the object it consumes.
- *
- * Since the machine and QEDGE_CONSUMED_BY nodes allocate
- * memory in the constructor, g_test_queue_destroy is used so
- * that after execution they can be safely free'd.  (The test's
- * ->before callback is also welcome to use g_test_queue_destroy).
- *
- * Note: as specified in walk_path() too, @arg is an array of
- * char *, where arg[0] is a pointer to the command line
- * string that will be used to properly start QEMU when executing
- * the test, and the remaining elements represent the actual objects
- * that will be allocated.
- */
-static void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc)
-{
-    int current = 0;
-    QGuestAllocator *alloc;
-    QOSGraphObject *parent = NULL;
-    QOSGraphEdge *edge;
-    QOSGraphNode *node;
-    void *edge_arg;
-    void *obj;
-
-    node = qos_graph_get_node(path[current]);
-    g_assert(node->type == QNODE_MACHINE);
-
-    obj = qos_machine_new(node, qts);
-    qos_object_queue_destroy(obj);
-
-    alloc = get_machine_allocator(obj);
-    if (p_alloc) {
-        *p_alloc = alloc;
-    }
-
-    for (;;) {
-        if (node->type != QNODE_INTERFACE) {
-            qos_object_start_hw(obj);
-            parent = obj;
-        }
-
-        /* follow edge and get object for next node constructor */
-        current++;
-        edge = qos_graph_get_edge(path[current - 1], path[current]);
-        node = qos_graph_get_node(path[current]);
-
-        if (node->type == QNODE_TEST) {
-            g_assert(qos_graph_edge_get_type(edge) == QEDGE_CONSUMED_BY);
-            return obj;
-        }
-
-        switch (qos_graph_edge_get_type(edge)) {
-        case QEDGE_PRODUCES:
-            obj = parent->get_driver(parent, path[current]);
-            break;
-
-        case QEDGE_CONSUMED_BY:
-            edge_arg = qos_graph_edge_get_arg(edge);
-            obj = qos_driver_new(node, obj, alloc, edge_arg);
-            qos_object_queue_destroy(obj);
-            break;
-
-        case QEDGE_CONTAINS:
-            obj = parent->get_device(parent, path[current]);
-            break;
-        }
-    }
-}
 
 /* The argument to run_one_test, which is the test function that is registered
  * with GTest, is a vector of strings.  The first item is the initial command
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 12/17] fuzz: Add fuzzer skeleton
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (10 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 11/17] fuzz: Move useful qos functions to separate object Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-09  9:43   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 13/17] fuzz: Add libqos support to the fuzzer Oleinik, Alexander
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

The code defines the lifecycle of the fuzzer, and provides rebooting,
vmload and device_load as means of resetting state between fuzz runs

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/fuzz/fuzz.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++
 tests/fuzz/fuzz.h |  70 +++++++++++++
 2 files changed, 315 insertions(+)
 create mode 100644 tests/fuzz/fuzz.c
 create mode 100644 tests/fuzz/fuzz.h

diff --git a/tests/fuzz/fuzz.c b/tests/fuzz/fuzz.c
new file mode 100644
index 0000000000..9e03e15d7b
--- /dev/null
+++ b/tests/fuzz/fuzz.c
@@ -0,0 +1,245 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "migration/qemu-file.h"
+
+#include "migration/qemu-file.h"
+#include "migration/global_state.h"
+#include "migration/savevm.h"
+#include "tests/libqtest.h"
+#include "migration/migration.h"
+#include "fuzz.h"
+#include "tests/libqos/qgraph.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/userfaultfd.h>
+#include <poll.h>
+#include <pthread.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+QTestState *s;
+
+QEMUFile *ramfile;
+QEMUFile *writefile;
+ram_disk *rd;
+
+
+typedef struct FuzzTargetState {
+        FuzzTarget *target;
+        QSLIST_ENTRY(FuzzTargetState) target_list;
+} FuzzTargetState;
+
+typedef QSLIST_HEAD(, FuzzTargetState) FuzzTargetList;
+
+FuzzTargetList *fuzz_target_list;
+
+/* Save just the VMStateDescriptors */
+void save_device_state(void)
+{
+    writefile = qemu_fopen_ram(&rd);
+    global_state_store();
+    qemu_save_device_state(writefile);
+    qemu_fflush(writefile);
+    ramfile = qemu_fopen_ro_ram(rd);
+}
+
+/* Save the entire vm state including RAM */
+void save_vm_state(void)
+{
+    writefile = qemu_fopen_ram(&rd);
+    vm_stop(RUN_STATE_SAVE_VM);
+    global_state_store();
+    qemu_savevm_state(writefile, NULL);
+    qemu_fflush(writefile);
+    ramfile = qemu_fopen_ro_ram(rd);
+}
+
+/* Reset state by rebooting */
+void reboot()
+{
+    qemu_system_reset(SHUTDOWN_CAUSE_NONE);
+}
+
+/* Restore device state */
+void load_device_state()
+{
+    qemu_freopen_ro_ram(ramfile);
+
+    int ret = qemu_load_device_state(ramfile);
+    if (ret < 0) {
+        printf("reset error\n");
+        exit(-1);
+    }
+}
+
+/* Restore full vm state */
+void load_vm_state()
+{
+    qemu_freopen_ro_ram(ramfile);
+
+    vm_stop(RUN_STATE_RESTORE_VM);
+
+    int ret = qemu_loadvm_state(ramfile);
+    if (ret < 0) {
+        printf("reset error\n");
+        exit(-1);
+    }
+    migration_incoming_state_destroy();
+    vm_start();
+}
+
+void qtest_setup()
+{
+    s = qtest_fuzz_init(NULL, NULL);
+    global_qtest = s;
+}
+
+void fuzz_add_target(const char *name, const char *description,
+        FuzzTarget *target)
+{
+
+    FuzzTargetState *tmp;
+    FuzzTargetState *target_state;
+    if (!fuzz_target_list) {
+        fuzz_target_list = g_new0(FuzzTargetList, 1);
+    }
+
+    QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
+        if (g_strcmp0(tmp->target->name->str, name) == 0) {
+            fprintf(stderr, "Error: Fuzz target name %s already in use\n",
+                    name);
+            abort();
+        }
+    }
+    target_state = g_new0(FuzzTargetState, 1);
+    target_state->target = g_new0(FuzzTarget, 1);
+    *(target_state->target) = *target;
+    target_state->target->name = g_string_new(name);
+    target_state->target->description = g_string_new(description);
+    QSLIST_INSERT_HEAD(fuzz_target_list, target_state, target_list);
+}
+
+
+static FuzzTarget *fuzz_get_target(char* name)
+{
+    FuzzTargetState *tmp;
+    if (!fuzz_target_list) {
+        fprintf(stderr, "Fuzz target list not initialized");
+        abort();
+    }
+
+    QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
+        if (g_strcmp0(tmp->target->name->str, name) == 0) {
+            break;
+        }
+    }
+    return tmp->target;
+}
+
+FuzzTarget *fuzz_target;
+
+
+
+static void usage(void)
+{
+    printf("Usage: ./fuzz --FUZZ_TARGET [LIBFUZZER ARGUMENTS]\n");
+    printf("where --FUZZ_TARGET is one of:\n");
+    FuzzTargetState *tmp;
+    if (!fuzz_target_list) {
+        fprintf(stderr, "Fuzz target list not initialized");
+        abort();
+    }
+    QSLIST_FOREACH(tmp, fuzz_target_list, target_list) {
+        printf(" --%s  : %s\n", tmp->target->name->str,
+                tmp->target->description->str);
+    }
+    exit(0);
+}
+
+static void enum_memory(void)
+{
+    /* TODO: Enumerate interesting memory using memory_region_is_ram */
+    return;
+}
+
+/* Executed for each fuzzing-input */
+int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size)
+{
+    /* e.g. Device bootstrapping */
+    if (fuzz_target->pre_fuzz) {
+        fuzz_target->pre_fuzz();
+    }
+
+    if (fuzz_target->fuzz) {
+        fuzz_target->fuzz(Data, Size);
+    }
+
+    /* e.g. Copy counter bitmap to shm*/
+    if (fuzz_target->post_fuzz) {
+        fuzz_target->post_fuzz();
+    }
+
+    /* e.g. Reboot the machine or vmload */
+    if (fuzz_target->reset) {
+        fuzz_target->reset();
+    }
+
+    return 0;
+}
+
+/* Executed once, prior to fuzzing */
+int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp)
+{
+
+    char *target_name;
+
+    /* Initialize qgraph and modules */
+    qos_graph_init();
+    module_call_init(MODULE_INIT_FUZZ_TARGET);
+    module_call_init(MODULE_INIT_QOM);
+    module_call_init(MODULE_INIT_LIBQOS);
+
+    if (*argc <= 1) {
+        usage();
+    }
+
+
+    /* Identify the fuzz target */
+    target_name = (*argv)[1];
+    target_name += 2;
+    fuzz_target = fuzz_get_target(target_name);
+
+    if (!fuzz_target) {
+        fprintf(stderr, "Error: Fuzz fuzz_target name %s not found\n",
+                target_name);
+        usage();
+    }
+
+    if (fuzz_target->pre_main) {
+        fuzz_target->pre_main();
+    }
+
+    /* Run QEMU's regular vl.c:main */
+    qemu_init(*(fuzz_target->main_argc), *(fuzz_target->main_argv), NULL);
+
+
+    /* Enumerate memory to identify mapped MMIO and I/O regions */
+    enum_memory();
+
+    /* Good place to do any one-time device initialization (such as QOS init) */
+    if (fuzz_target->pre_save_state) {
+        fuzz_target->pre_save_state();
+    }
+
+    /* If configured, this is where we save vm or device state to ramdisk */
+    if (fuzz_target->save_state) {
+        fuzz_target->save_state();
+    }
+
+    return 0;
+}
diff --git a/tests/fuzz/fuzz.h b/tests/fuzz/fuzz.h
new file mode 100644
index 0000000000..46ec38d4ea
--- /dev/null
+++ b/tests/fuzz/fuzz.h
@@ -0,0 +1,70 @@
+#ifndef FUZZER_H_
+#define FUZZER_H_
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "exec/memory.h"
+#include "tests/libqtest.h"
+#include "migration/qemu-file.h"
+
+#include <linux/userfaultfd.h>
+
+
+extern QTestState *s;
+extern QEMUFile *writefile;
+extern QEMUFile *ramfile;
+extern ram_disk *rd;
+
+typedef struct FuzzTarget {
+    GString *name;
+    GString *description;
+    void(*pre_main)(void);
+    void(*pre_save_state)(void);
+    void(*save_state)(void);
+    void(*reset)(void);
+    void(*pre_fuzz)(void);
+    void(*fuzz)(const unsigned char*, size_t);
+    void(*post_fuzz)(void);
+    int *main_argc;
+    char ***main_argv;
+} FuzzTarget;
+
+
+void save_device_state(void);
+void save_vm_state(void);
+void reboot(void);
+
+void load_device_state(void);
+void load_vm_state(void);
+
+
+void save_device_state(void);
+void qtest_setup(void);
+void fuzz_register_mr(const MemoryRegion *mr);
+
+extern FuzzTarget *fuzz_target;
+
+typedef struct fuzz_memory_region {
+    bool io;
+    uint64_t start;
+    uint64_t length;
+    struct fuzz_memory_region *next;
+} fuzz_memory_region;
+
+extern fuzz_memory_region *fuzz_memory_region_head;
+extern fuzz_memory_region *fuzz_memory_region_tail;
+
+extern uint64_t total_io_mem;
+extern uint64_t total_ram_mem;
+
+
+
+void fuzz_add_target(const char *name, const char *description, FuzzTarget
+        *target);
+
+int LLVMFuzzerTestOneInput(const unsigned char *Data, size_t Size);
+int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp);
+
+#endif
+
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 13/17] fuzz: Add libqos support to the fuzzer
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (11 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 12/17] fuzz: Add fuzzer skeleton Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 14/17] fuzz: Add forking " Oleinik, Alexander
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/fuzz/qos_fuzz.c    |  58 ++++++++++++
 tests/fuzz/qos_fuzz.h    |  23 +++++
 tests/fuzz/qos_helpers.c | 190 +++++++++++++++++++++++++++++++++++++++
 tests/fuzz/qos_helpers.h |  17 ++++
 4 files changed, 288 insertions(+)
 create mode 100644 tests/fuzz/qos_fuzz.c
 create mode 100644 tests/fuzz/qos_fuzz.h
 create mode 100644 tests/fuzz/qos_helpers.c
 create mode 100644 tests/fuzz/qos_helpers.h

diff --git a/tests/fuzz/qos_fuzz.c b/tests/fuzz/qos_fuzz.c
new file mode 100644
index 0000000000..80a22793d6
--- /dev/null
+++ b/tests/fuzz/qos_fuzz.c
@@ -0,0 +1,58 @@
+
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "qemu/main-loop.h"
+
+#include "libqos/malloc.h"
+#include "libqos/qgraph.h"
+#include "libqos/qgraph_internal.h"
+
+#include "hw/virtio/virtio-net.h"
+#include "hw/virtio/virtio.h"
+#include "libqos/virtio-net.h"
+#include "fuzz.h"
+#include "qos_fuzz.h"
+#include "qos_helpers.h"
+#include "tests/libqos/qgraph.h"
+#include "tests/libqtest.h"
+
+
+fuzz_memory_region *fuzz_memory_region_head;
+fuzz_memory_region *fuzz_memory_region_tail;
+
+uint64_t total_io_mem;
+uint64_t total_ram_mem;
+
+
+void fuzz_add_qos_target(const char *name,
+        const char *description,
+        const char *interface,
+        QOSGraphTestOptions *opts,
+        FuzzTarget *fuzz_opts
+        )
+{
+    qos_add_test(name, interface, NULL, opts);
+    fuzz_opts->main_argc = &qos_argc;
+    fuzz_opts->main_argv = &qos_argv;
+    fuzz_add_target(name, description, fuzz_opts);
+}
+
+
+/* Do what is normally done in qos_test.c:main */
+void qos_setup(void){
+    qtest_setup();
+    qos_set_machines_devices_available();
+    qos_graph_foreach_test_path(walk_path);
+    qos_build_main_args();
+}
+
+void qos_init_path(void)
+{
+    qos_obj = qos_allocate_objects(global_qtest, &qos_alloc);
+}
diff --git a/tests/fuzz/qos_fuzz.h b/tests/fuzz/qos_fuzz.h
new file mode 100644
index 0000000000..68d0684a7c
--- /dev/null
+++ b/tests/fuzz/qos_fuzz.h
@@ -0,0 +1,23 @@
+#ifndef _QOS_FUZZ_H_
+#define _QOS_FUZZ_H_
+
+#include "tests/libqos/qgraph.h"
+
+int qos_fuzz(const unsigned char *Data, size_t Size);
+void qos_setup(void);
+
+extern char **fuzz_path_vec;
+extern int qos_argc;
+extern char **qos_argv;
+extern void *qos_obj;
+extern QGuestAllocator *qos_alloc;
+
+
+void fuzz_add_qos_target(const char *name,
+        const char *description,
+        const char *interface,
+        QOSGraphTestOptions *opts,
+        FuzzTarget *fuzz_opts);
+
+void qos_init_path(void);
+#endif
diff --git a/tests/fuzz/qos_helpers.c b/tests/fuzz/qos_helpers.c
new file mode 100644
index 0000000000..c65f32e78b
--- /dev/null
+++ b/tests/fuzz/qos_helpers.c
@@ -0,0 +1,190 @@
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qos_helpers.h"
+#include "fuzz.h"
+#include "qapi/qmp/qlist.h"
+#include "libqtest.h"
+#include "sysemu/qtest.h"
+#include "libqos/qgraph.h"
+#include "libqos/qgraph_internal.h"
+#include "libqos/qos_external.h"
+#include "qapi/qapi-commands-machine.h"
+#include "qapi/qapi-commands-misc.h"
+#include "qapi/qapi-commands-qom.h"
+#include <wordexp.h>
+#include "sysemu/sysemu.h"
+#include "sysemu/cpus.h"
+
+
+
+/*
+ * Replaced the qmp commands with direct qmp_marshal calls.
+ * Probably there is a better way to do this
+ */
+void qos_set_machines_devices_available(void)
+{
+    QDict *req = qdict_new();
+    QObject *response;
+    QDict *args = qdict_new();
+    QList *lst;
+    Error *err = NULL;
+
+    qmp_marshal_query_machines(NULL, &response, &err);
+    assert(!err);
+    lst = qobject_to(QList, response);
+    apply_to_qlist(lst, true);
+
+    qobject_unref(response);
+
+
+    qdict_put_str(req, "execute", "qom-list-types");
+    qdict_put_str(args, "implements", "device");
+    qdict_put_bool(args, "abstract", true);
+    qdict_put_obj(req, "arguments", (QObject *) args);
+
+    qmp_marshal_qom_list_types(args, &response, &err);
+    assert(!err);
+    lst = qobject_to(QList, response);
+    apply_to_qlist(lst, false);
+    qobject_unref(response);
+    qobject_unref(req);
+}
+
+static char **current_path;
+
+
+void *qos_allocate_objects(QTestState *qts, QGuestAllocator **p_alloc)
+{
+    return allocate_objects(qts, current_path + 1, p_alloc);
+}
+
+
+char **fuzz_path_vec;
+void *qos_obj;
+QGuestAllocator *qos_alloc;
+
+int qos_argc;
+char **qos_argv;
+
+void qos_build_main_args()
+{
+    char **path = fuzz_path_vec;
+    QOSGraphNode *test_node;
+    GString *cmd_line = g_string_new(path[0]);
+    void *test_arg;
+
+    /* Before test */
+    current_path = path;
+    test_node = qos_graph_get_node(path[(g_strv_length(path) - 1)]);
+    test_arg = test_node->u.test.arg;
+    if (test_node->u.test.before) {
+        test_arg = test_node->u.test.before(cmd_line, test_arg);
+    }
+
+    /* Prepend the arguments that we need */
+    g_string_prepend(cmd_line,
+            "qemu-system-i386 -display none -machine accel=fuzz -m 16 ");
+    wordexp_t result;
+    wordexp(cmd_line->str, &result, 0);
+    qos_argc = result.we_wordc;
+    qos_argv = result.we_wordv;
+
+    g_string_free(cmd_line, true);
+}
+
+/*
+ * This function is largely a copy of qos-test.c:
+ * TODO: Possibly add a callback argument to walk_path to use one function
+ * for both fuzzing and normal testing
+ */
+void walk_path(QOSGraphNode *orig_path, int len)
+{
+    QOSGraphNode *path;
+    QOSGraphEdge *edge;
+
+    /* etype set to QEDGE_CONSUMED_BY so that machine can add to the command line */
+    QOSEdgeType etype = QEDGE_CONSUMED_BY;
+
+    /* twice QOS_PATH_MAX_ELEMENT_SIZE since each edge can have its arg */
+    char **path_vec = g_new0(char *, (QOS_PATH_MAX_ELEMENT_SIZE * 2));
+    int path_vec_size = 0;
+
+    char *after_cmd, *before_cmd, *after_device;
+    GString *after_device_str = g_string_new("");
+    char *node_name = orig_path->name, *path_str;
+
+    GString *cmd_line = g_string_new("");
+    GString *cmd_line2 = g_string_new("");
+
+    path = qos_graph_get_node(node_name); /* root */
+    node_name = qos_graph_edge_get_dest(path->path_edge); /* machine name */
+
+    path_vec[path_vec_size++] = node_name;
+    path_vec[path_vec_size++] = qos_get_machine_type(node_name);
+
+    for (;;) {
+        path = qos_graph_get_node(node_name);
+        if (!path->path_edge) {
+            break;
+        }
+
+        node_name = qos_graph_edge_get_dest(path->path_edge);
+
+        /* append node command line + previous edge command line */
+        if (path->command_line && etype == QEDGE_CONSUMED_BY) {
+            g_string_append(cmd_line, path->command_line);
+            g_string_append(cmd_line, after_device_str->str);
+            g_string_truncate(after_device_str, 0);
+        }
+
+        path_vec[path_vec_size++] = qos_graph_edge_get_name(path->path_edge);
+        /* detect if edge has command line args */
+        after_cmd = qos_graph_edge_get_after_cmd_line(path->path_edge);
+        after_device = qos_graph_edge_get_extra_device_opts(path->path_edge);
+        before_cmd = qos_graph_edge_get_before_cmd_line(path->path_edge);
+        edge = qos_graph_get_edge(path->name, node_name);
+        etype = qos_graph_edge_get_type(edge);
+
+        if (before_cmd) {
+            g_string_append(cmd_line, before_cmd);
+        }
+        if (after_cmd) {
+            g_string_append(cmd_line2, after_cmd);
+        }
+        if (after_device) {
+            g_string_append(after_device_str, after_device);
+        }
+    }
+
+    path_vec[path_vec_size++] = NULL;
+    g_string_append(cmd_line, after_device_str->str);
+    g_string_free(after_device_str, true);
+
+    g_string_append(cmd_line, cmd_line2->str);
+    g_string_free(cmd_line2, true);
+
+    /*
+     * here position 0 has <arch>/<machine>, position 1 has <machine>.
+     * The path must not have the <arch>, qtest_add_data_func adds it.
+     */
+    path_str = g_strjoinv("/", path_vec + 1);
+
+    /* Check that this is the test we care about: */
+    char *test_name = strrchr(path_str, '/') + 1;
+    if (strcmp(test_name, fuzz_target->name->str) == 0) {
+        /*
+         * put arch/machine in position 1 so run_one_test can do its work
+         * and add the command line at position 0.
+         */
+        path_vec[1] = path_vec[0];
+        path_vec[0] = g_string_free(cmd_line, false);
+        printf("path_str: %s path_vec[0]: %s [1]: %s\n", path_str, path_vec[0],
+                path_vec[1]);
+
+        fuzz_path_vec = path_vec;
+    } else {
+        g_free(path_vec);
+    }
+
+    g_free(path_str);
+}
diff --git a/tests/fuzz/qos_helpers.h b/tests/fuzz/qos_helpers.h
new file mode 100644
index 0000000000..baf9b49e9c
--- /dev/null
+++ b/tests/fuzz/qos_helpers.h
@@ -0,0 +1,17 @@
+#ifndef QOS_HELPERS_H
+#define QOS_HELPERS_H
+
+#include "qemu/osdep.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/qmp/qbool.h"
+#include "qapi/qmp/qstring.h"
+#include "libqtest.h"
+#include "qapi/qmp/qlist.h"
+#include "libqos/qgraph_internal.h"
+
+
+void qos_set_machines_devices_available(void);
+void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc);
+void walk_path(QOSGraphNode *orig_path, int len);
+void qos_build_main_args(void);
+#endif
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 14/17] fuzz: Add forking support to the fuzzer
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (12 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 13/17] fuzz: Add libqos support to the fuzzer Oleinik, Alexander
@ 2019-08-05  7:11 ` " Oleinik, Alexander
  2019-08-09  9:46   ` Stefan Hajnoczi
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 15/17] fuzz: Add general qtest fuzz-target Oleinik, Alexander
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Forking is a simple way of ensuring that state doesn't leak between
runs. This patch depends on a modification to libfuzzer:
https://reviews.llvm.org/D65672

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/fuzz/fuzzer_hooks.c | 62 +++++++++++++++++++++++++++++++++++++++
 tests/fuzz/fuzzer_hooks.h | 21 +++++++++++++
 2 files changed, 83 insertions(+)
 create mode 100644 tests/fuzz/fuzzer_hooks.c
 create mode 100644 tests/fuzz/fuzzer_hooks.h

diff --git a/tests/fuzz/fuzzer_hooks.c b/tests/fuzz/fuzzer_hooks.c
new file mode 100644
index 0000000000..87c94ef65f
--- /dev/null
+++ b/tests/fuzz/fuzzer_hooks.c
@@ -0,0 +1,62 @@
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "fuzzer_hooks.h"
+
+#include <dlfcn.h>
+#include <elf.h>
+
+
+
+void *counter_shm;
+size_t feature_shm_len;
+uintptr_t feature_shm;
+size_t offset;
+
+typedef struct CoverageRegion {
+    uint8_t *start;
+    size_t length;
+    bool store; /* Set this if it needs to be copied to the forked process */
+} CoverageRegion;
+
+CoverageRegion regions[10];
+int region_index;
+
+
+void counter_shm_init(void)
+{
+    LLVMFuzzerIterateFeatureRegions(&measure_shm_size);
+    feature_shm = (uintptr_t)mmap(NULL, feature_shm_len,
+            PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
+}
+
+void counter_shm_store(void)
+{
+    offset = 0;
+    LLVMFuzzerIterateFeatureRegions(&feature_store);
+}
+
+void counter_shm_load(void)
+{
+    offset = 0;
+    LLVMFuzzerIterateFeatureRegions(&feature_load);
+}
+
+void feature_load(void *start, size_t len)
+{
+    memcpy(start, (void *)(feature_shm + offset), len);
+    offset += len;
+}
+
+void feature_store(void *start, size_t len)
+{
+    memcpy((void *)(feature_shm + offset), start, len);
+    offset += len;
+}
+
+void measure_shm_size(void *start, size_t len)
+{
+    feature_shm_len += len;
+}
+
diff --git a/tests/fuzz/fuzzer_hooks.h b/tests/fuzz/fuzzer_hooks.h
new file mode 100644
index 0000000000..2f411193dd
--- /dev/null
+++ b/tests/fuzz/fuzzer_hooks.h
@@ -0,0 +1,21 @@
+#ifndef FUZZER_HOOKS_H
+#define FUZZER_HOOKS_H
+
+
+/* NOTE: Pending https://reviews.llvm.org/D65672
+ * Alternatively, a similar functionality can be added fairly straightforwardly
+ * with AFL deferred fork mode, albeit requiring a different fuzzer and compiler
+ * https://github.com/mirrorer/afl/blob/master/llvm_mode/README.llvm#L82
+ */
+extern void LLVMFuzzerIterateFeatureRegions(void (*CB)(void *, size_t));
+
+void measure_shm_size(void *start, size_t len);
+
+void counter_shm_init(void);
+void counter_shm_store(void);
+void counter_shm_load(void);
+void feature_load(void *start, size_t len);
+void feature_store(void *start, size_t len);
+
+#endif
+
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 15/17] fuzz: Add general qtest fuzz-target
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (13 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 14/17] fuzz: Add forking " Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 16/17] fuzz: Add virtio-net fuzz targets Oleinik, Alexander
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/fuzz/qtest_fuzz.c | 260 ++++++++++++++++++++++++++++++++++++++++
 tests/fuzz/qtest_fuzz.h |  37 ++++++
 2 files changed, 297 insertions(+)
 create mode 100644 tests/fuzz/qtest_fuzz.c
 create mode 100644 tests/fuzz/qtest_fuzz.h

diff --git a/tests/fuzz/qtest_fuzz.c b/tests/fuzz/qtest_fuzz.c
new file mode 100644
index 0000000000..a4560535e1
--- /dev/null
+++ b/tests/fuzz/qtest_fuzz.c
@@ -0,0 +1,260 @@
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "sysemu/sysemu.h"
+#include "qemu/main-loop.h"
+#include <wordexp.h>
+#include "qemu-common.h"
+#include "fuzzer_hooks.h"
+
+
+#include "fuzz.h"
+#include "qtest_fuzz.h"
+#include "tests/libqtest.h"
+#include "fuzz/qos_fuzz.h"
+
+
+/* Make sure that the io_port is mapped to some device */
+static uint16_t normalize_io_port(uint64_t addr)
+{
+    return addr;
+    addr = addr % total_io_mem;
+    fuzz_memory_region *fmr = fuzz_memory_region_head;
+    while (addr != 0) {
+        if (!fmr->io) {
+            fmr = fmr->next;
+            continue;
+        }
+        if (addr <= fmr->length) {
+            addr = fmr->start + addr;
+            break;
+        }
+        addr -= fmr->length + 1;
+        fmr = fmr->next;
+    }
+    /* Stuff that times out or hotplugs.. */
+    if (addr >= 0x5655 && addr <= 0x565b) {
+        return 0;
+    }
+    if (addr >= 0x510 && addr <= 0x518) {
+        return 0;
+    }
+    /* PCI Hotplug */
+    if (addr >= 0xae00 && addr <= 0xae13) {
+        return 0;
+    }
+    /* CPU Hotplug */
+    if (addr >= 0xaf00 && addr <= 0xaf1f) {
+        return 0;
+    }
+    return addr;
+}
+
+/* Make sure that the memory address is mapped to some interesting device */
+static uint16_t normalize_mem_addr(uint64_t addr)
+{
+    return addr;
+    addr = addr % total_ram_mem;
+    fuzz_memory_region *fmr = fuzz_memory_region_head;
+    while (addr != 0) {
+        if (fmr->io) {
+            fmr = fmr->next;
+            continue;
+        }
+        if (addr <= fmr->length) {
+            return fmr->start + addr;
+        }
+        addr -= fmr->length + 1;
+        fmr = fmr->next;
+    }
+    return addr;
+}
+
+static void qtest_fuzz(const unsigned char *Data, size_t Size)
+{
+    const unsigned char *pos = Data;
+    const unsigned char *End = Data + Size;
+
+    qtest_cmd *cmd;
+
+    while (pos < Data + Size) {
+        /* Translate the fuzz input to a qtest command */
+        cmd = &commands[(*pos) % (sizeof(commands) / sizeof(qtest_cmd))];
+        pos++;
+
+        if (strcmp(cmd->name, "clock_step") == 0) {
+            /* TODO: This times out */
+            /* qtest_clock_step_next(s); */
+        } else if (strcmp(cmd->name, "outb") == 0) {
+            if (pos + sizeof(uint16_t) + sizeof(uint8_t) < End) {
+                uint16_t addr = *(int16_t *)(pos);
+                pos += sizeof(uint16_t);
+                uint8_t val = *(uint16_t *)(pos);
+                pos += sizeof(uint8_t);
+                addr = normalize_io_port(addr);
+                qtest_outb(s, addr, val);
+            }
+        } else if (strcmp(cmd->name, "outw") == 0) {
+            if (pos + sizeof(uint16_t) + sizeof(uint16_t) < End) {
+                uint16_t addr = *(int16_t *)(pos);
+                pos += sizeof(uint16_t);
+                uint16_t val = *(uint16_t *)(pos);
+                pos += sizeof(uint16_t);
+                addr = normalize_io_port(addr);
+                qtest_outw(s, addr, val);
+            }
+        } else if (strcmp(cmd->name, "outl") == 0) {
+            if (pos + sizeof(uint16_t) + sizeof(uint32_t) < End) {
+                uint16_t addr = *(int16_t *)(pos);
+                pos += sizeof(uint16_t);
+                uint32_t val = *(uint32_t *)(pos);
+                pos += sizeof(uint32_t);
+                addr = normalize_io_port(addr);
+                qtest_outl(s, addr, val);
+            }
+        } else if (strcmp(cmd->name, "inb") == 0) {
+            if (pos + sizeof(uint16_t) < End) {
+                uint16_t addr = *(int16_t *)(pos);
+                pos += sizeof(uint16_t);
+                addr = normalize_io_port(addr);
+                qtest_inb(s, addr);
+            }
+        } else if (strcmp(cmd->name, "inw") == 0) {
+            if (pos + sizeof(uint16_t) < End) {
+                uint16_t addr = *(int16_t *)(pos);
+                pos += sizeof(uint16_t);
+                addr = normalize_io_port(addr);
+                qtest_inw(s, addr);
+            }
+        } else if (strcmp(cmd->name, "inl") == 0) {
+            if (pos + sizeof(uint16_t) < End) {
+                uint16_t addr = *(int16_t *)(pos);
+                pos += sizeof(uint16_t);
+                addr = normalize_io_port(addr);
+                qtest_inl(s, addr);
+            }
+        } else if (strcmp(cmd->name, "writeb") == 0) {
+            if (pos + sizeof(uint32_t) + sizeof(uint8_t) < End) {
+                uint32_t addr = *(int32_t *)(pos);
+                pos += sizeof(uint32_t);
+                uint8_t val = *(uint8_t *)(pos);
+                pos += sizeof(uint8_t);
+                addr = normalize_mem_addr(addr);
+                qtest_writeb(s, addr, val);
+            }
+        } else if (strcmp(cmd->name, "writew") == 0) {
+            if (pos + sizeof(uint32_t) + sizeof(uint16_t) < End) {
+                uint32_t addr = *(int32_t *)(pos);
+                pos += sizeof(uint32_t);
+                uint16_t val = *(uint16_t *)(pos);
+                pos += sizeof(uint16_t);
+                addr = normalize_mem_addr(addr);
+                qtest_writew(s, addr, val);
+            }
+        } else if (strcmp(cmd->name, "writel") == 0) {
+            if (pos + sizeof(uint32_t) + sizeof(uint32_t) < End) {
+                uint32_t addr = *(int32_t *)(pos);
+                pos += sizeof(uint32_t);
+                uint32_t val = *(uint32_t *)(pos);
+                pos += sizeof(uint32_t);
+                addr = normalize_mem_addr(addr);
+                qtest_writel(s, addr, val);
+            }
+        } else if (strcmp(cmd->name, "readb") == 0) {
+            if (pos + sizeof(uint32_t) < End) {
+                uint32_t addr = *(int32_t *)(pos);
+                pos += sizeof(uint32_t);
+                addr = normalize_mem_addr(addr);
+                qtest_readb(s, addr);
+            }
+        } else if (strcmp(cmd->name, "readw") == 0) {
+            if (pos + sizeof(uint32_t) < End) {
+                uint32_t addr = *(int32_t *)(pos);
+                pos += sizeof(uint32_t);
+                addr = normalize_mem_addr(addr);
+                qtest_readw(s, addr); }
+        } else if (strcmp(cmd->name, "readl") == 0) {
+            if (pos + sizeof(uint32_t) < End) {
+                uint32_t addr = *(int32_t *)(pos);
+                pos += sizeof(uint32_t);
+                addr = normalize_mem_addr(addr);
+                qtest_readl(s, addr);
+            }
+        } else if (strcmp(cmd->name, "write_dma") == 0) {
+            if (pos + sizeof(uint32_t) + sizeof(uint16_t) < End) {
+                uint32_t addr = *(int32_t *)(pos);
+                pos += sizeof(uint32_t);
+                uint32_t val = 0x100000;
+                addr = normalize_mem_addr(addr);
+                qtest_writel(s, addr, val);
+            }
+        } else if (strcmp(cmd->name, "out_dma") == 0) {
+            if (pos + sizeof(uint16_t) + sizeof(uint16_t) < End) {
+                uint16_t addr  =  *(int16_t *)(pos);
+                pos += sizeof(uint16_t);
+                uint32_t val = 0x100000;
+                addr = normalize_io_port(addr);
+                qtest_outl(s, addr, val);
+            }
+        }
+        /* main_loop_wait(false); */
+    }
+}
+
+static void *net_test_setup_nosocket(GString *cmd_line, void *arg)
+{
+    g_string_append(cmd_line, " -netdev hubport,hubid=0,id=hs0 ");
+    return arg;
+}
+
+static void fuzz_fork(const unsigned char *Data, size_t Size)
+{
+    if (fork() == 0) {
+        qtest_fuzz(Data, Size);
+        counter_shm_store();
+        _Exit(0);
+    } else {
+        wait(NULL);
+        counter_shm_load();
+    }
+}
+
+static void fork_pre_main(void)
+{
+    qos_setup();
+    counter_shm_init();
+}
+
+int qtest_argc;
+char **qtest_argv;
+static void register_qtest_fuzz_targets(void)
+{
+    QOSGraphTestOptions opts = {
+        .before = net_test_setup_nosocket,
+    };
+    FuzzTarget fuzz_opts = {
+        .pre_main = qos_setup,
+        .pre_save_state = qos_init_path,
+        .save_state = &save_vm_state,
+        .reset = &load_vm_state,
+        .pre_fuzz = NULL,
+        .fuzz = &qtest_fuzz,
+        .post_fuzz = NULL,
+    };
+    fuzz_add_qos_target("qtest-fuzz", "fuzz qtest commands and a dma buffer. \
+            Reset device state for each run", "e1000e", &opts, &fuzz_opts);
+
+    fuzz_opts.pre_main = &fork_pre_main;
+    fuzz_opts.pre_fuzz = NULL;
+    fuzz_opts.fuzz = &fuzz_fork;
+    fuzz_opts.reset = NULL;
+    fuzz_add_qos_target("qtest-fork-fuzz", "fuzz qtest commands and a dma \
+            buffer. Use COW/forking to reset state", "e1000e", &opts,
+            &fuzz_opts);
+
+}
+
+fuzz_target_init(register_qtest_fuzz_targets);
diff --git a/tests/fuzz/qtest_fuzz.h b/tests/fuzz/qtest_fuzz.h
new file mode 100644
index 0000000000..c4cf08f5a2
--- /dev/null
+++ b/tests/fuzz/qtest_fuzz.h
@@ -0,0 +1,37 @@
+#ifndef _QTEST_FUZZ_H_
+#define _QTEST_FUZZ_H_
+
+typedef struct qtest_cmd {
+    char name[32];
+    uint8_t size;
+} qtest_cmd;
+
+typedef uint32_t addr_type;
+
+static qtest_cmd commands[] = {
+    {"clock_step", 0},
+    {"clock_step", 0},
+    {"clock_set", 1},
+    {"outb", 2},
+    {"outw", 2},
+    {"outl", 2},
+    {"inb", 1},
+    {"inw", 1},
+    {"inl", 1},
+    {"writeb", 2},
+    {"writew", 2},
+    {"writel", 2},
+    {"writeq", 2},
+    {"readb", 1},
+    {"readw", 1},
+    {"readl", 1},
+    {"readq", 1},
+    {"read", 2},
+    {"write", 3},
+    {"b64read", 2},
+    {"b64write", 10},
+    {"memset", 3},
+    {"write_dma", 2},
+    {"out_dma", 2},
+};
+#endif
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 16/17] fuzz: Add virtio-net fuzz targets
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (14 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 15/17] fuzz: Add general qtest fuzz-target Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 17/17] fuzz: Add fuzz accelerator type Oleinik, Alexander
  2019-08-05  8:19 ` [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support no-reply
  17 siblings, 0 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/fuzz/virtio-net-fuzz.c | 254 +++++++++++++++++++++++++++++++++++
 1 file changed, 254 insertions(+)
 create mode 100644 tests/fuzz/virtio-net-fuzz.c

diff --git a/tests/fuzz/virtio-net-fuzz.c b/tests/fuzz/virtio-net-fuzz.c
new file mode 100644
index 0000000000..dfba2e3ca7
--- /dev/null
+++ b/tests/fuzz/virtio-net-fuzz.c
@@ -0,0 +1,254 @@
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "exec/memory.h"
+#include "sysemu/sysemu.h"
+#include "qemu/main-loop.h"
+
+#include "hw/virtio/virtio-net.h"
+#include "hw/virtio/virtio.h"
+#include "tests/libqos/virtio-net.h"
+#include "fuzzer_hooks.h"
+#include "snapshotting.h"
+
+#include "fuzz.h"
+#include "qos_fuzz.h"
+
+#define MAX_INPUT_BUFFERS 10
+
+typedef struct vq_action {
+    uint8_t queue;
+    uint8_t length;
+    uint8_t write;
+    uint8_t next;
+    bool kick;
+} vq_action;
+
+static void virtio_net_ctrl_fuzz(const unsigned char *Data, size_t Size)
+{
+    uint64_t req_addr[10];
+    int reqi = 0;
+    uint32_t free_head;
+
+    QGuestAllocator *t_alloc = qos_alloc;
+
+    QVirtioNet *net_if = qos_obj;
+    QVirtioDevice *dev = net_if->vdev;
+    QVirtQueue *q;
+    vq_action vqa;
+    int iters = 0;
+    while (true) {
+        if (Size < sizeof(vqa)) {
+            break;
+        }
+        vqa = *((vq_action *)Data);
+        Data += sizeof(vqa);
+        Size -= sizeof(vqa);
+
+        q = net_if->queues[2];
+
+        vqa.length = vqa.length >= Size ? Size :  vqa.length;
+
+        req_addr[reqi] = guest_alloc(t_alloc, vqa.length);
+        memwrite(req_addr[reqi], Data, vqa.length);
+        if (iters == 0) {
+            free_head = qvirtqueue_add(q, req_addr[reqi], vqa.length,
+                    vqa.write, vqa.next);
+        } else {
+            qvirtqueue_add(q, req_addr[reqi], vqa.length, vqa.write , vqa.next);
+        }
+        iters++;
+        reqi++;
+        if (iters == 10) {
+            break;
+        }
+        Data += vqa.length;
+        Size -= vqa.length;
+    }
+    if (iters) {
+        qvirtqueue_kick(dev, q, free_head);
+        /* qtest_clock_step_next(s); */
+        main_loop_wait(false);
+        for (int i = 0; i < reqi; i++) {
+            guest_free(t_alloc, req_addr[i]);
+        }
+    }
+    qtest_clear_rxbuf(s);
+    qos_object_queue_destroy(qos_obj);
+}
+
+static void virtio_net_ctrl_fuzz_multi(const unsigned char *Data, size_t Size)
+{
+    uint64_t req_addr[10];
+    int reqi = 0;
+    uint32_t free_head;
+
+    QGuestAllocator *t_alloc = qos_alloc;
+
+    QVirtioNet *net_if = qos_obj;
+    QVirtioDevice *dev = net_if->vdev;
+    QVirtQueue *q;
+    vq_action vqa;
+    int iters = 0;
+    while (Size >= sizeof(vqa)) {
+        vqa = *((vq_action *)Data);
+        Data += sizeof(vqa);
+        Size -= sizeof(vqa);
+        if (vqa.kick && free_head) {
+            qvirtqueue_kick(dev, q, free_head);
+            qtest_clock_step_next(s);
+            main_loop_wait(false);
+            for (int i = 0; i < reqi; i++) {
+                guest_free(t_alloc, req_addr[i]);
+            }
+            reqi = 0;
+        } else {
+            q = net_if->queues[2];
+
+            vqa.length = vqa.length >= Size ? Size :  vqa.length;
+
+            req_addr[reqi] = guest_alloc(t_alloc, vqa.length);
+            memwrite(req_addr[reqi], Data, vqa.length);
+            if (iters == 0) {
+                free_head = qvirtqueue_add(q, req_addr[reqi], vqa.length,
+                        vqa.write, vqa.next);
+            } else {
+                qvirtqueue_add(q, req_addr[reqi], vqa.length, vqa.write,
+                        vqa.next) ;
+            }
+            iters++;
+            reqi++;
+            if (iters == 10) {
+                break;
+            }
+            Data += vqa.length;
+            Size -= vqa.length;
+        }
+    }
+    qtest_clear_rxbuf(s);
+    qos_object_queue_destroy(qos_obj);
+}
+
+int *sv;
+static void virtio_net_tx_fuzz(const unsigned char *Data, size_t Size)
+{
+    uint64_t req_addr[10];
+    int reqi = 0;
+    uint32_t free_head;
+
+    QGuestAllocator *t_alloc = qos_alloc;
+
+    QVirtioNet *net_if = qos_obj;
+    QVirtioDevice *dev = net_if->vdev;
+    QVirtQueue *q;
+    vq_action vqa;
+    int iters = 0;
+    while (true) {
+        if (Size < sizeof(vqa)) {
+            break;
+        }
+        vqa = *((vq_action *)Data);
+        Data += sizeof(vqa);
+        Size -= sizeof(vqa);
+
+        q = net_if->queues[1];
+
+        vqa.length = vqa.length >= Size ? Size :  vqa.length;
+
+        req_addr[reqi] = guest_alloc(t_alloc, vqa.length);
+        memwrite(req_addr[reqi], Data, vqa.length);
+        if (iters == 0) {
+            free_head = qvirtqueue_add(q, req_addr[reqi], vqa.length,
+                    vqa.write, vqa.next);
+        } else {
+            qvirtqueue_add(q, req_addr[reqi], vqa.length, vqa.write, vqa.next);
+        }
+        iters++;
+        reqi++;
+        if (iters == 10) {
+            break;
+        }
+        Data += vqa.length;
+        Size -= vqa.length;
+    }
+    if (iters) {
+        qvirtqueue_kick(dev, q, free_head);
+        qtest_clock_step_next(s);
+        main_loop_wait(false);
+        for (int i = 0; i < reqi; i++) {
+            guest_free(t_alloc, req_addr[i]);
+        }
+    }
+    qtest_clear_rxbuf(s);
+    qos_object_queue_destroy(qos_obj);
+}
+
+static void *virtio_net_test_setup_socket(GString *cmd_line, void *arg)
+{
+    if (!sv) {
+        sv = g_new(int, 2);
+        int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sv);
+        fcntl(sv[0], F_SETFL, O_NONBLOCK);
+        g_assert_cmpint(ret, !=, -1);
+    }
+    g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ", sv[1]);
+    return arg;
+}
+
+static void fuzz_fork(const unsigned char *Data, size_t Size)
+{
+    if (fork() == 0) {
+        main_loop_wait(false);
+        virtio_net_ctrl_fuzz(Data, Size);
+        counter_shm_store();
+        _Exit(0);
+    } else {
+        wait(NULL);
+        counter_shm_load();
+    }
+}
+
+static void fork_pre_main(void)
+{
+    qos_setup();
+    counter_shm_init();
+}
+
+static void register_virtio_net_fuzz_targets(void)
+{
+    QOSGraphTestOptions opts = {
+        .before = virtio_net_test_setup_socket,
+    };
+    FuzzTarget fuzz_opts = {
+        .pre_main = qos_setup,
+        .pre_save_state = NULL,
+        .save_state = NULL,
+        .reset = &reboot,
+        .pre_fuzz = &qos_init_path,
+        .fuzz = &virtio_net_ctrl_fuzz,
+        .post_fuzz = NULL,
+    };
+    fuzz_add_qos_target("virtio-net-ctrl-fuzz", "virtio-net ctrl virtqueue \
+            fuzzer", "virtio-net", &opts, &fuzz_opts);
+
+    fuzz_opts.fuzz = &virtio_net_ctrl_fuzz_multi;
+    fuzz_add_qos_target("virtio-net-ctrl-multi-fuzz", "virtio-net ctrl\
+             virtqueue  fuzzer with multiple kicks", "virtio-net", &opts,
+            &fuzz_opts);
+
+    fuzz_opts.fuzz = &virtio_net_tx_fuzz;
+    fuzz_add_qos_target("virtio-net-tx-fuzz", "virtio-net tx virtqueue fuzzer",
+            "virtio-net", &opts, &fuzz_opts);
+
+    fuzz_opts.pre_main = &fork_pre_main;
+    fuzz_opts.pre_save_state = &qos_init_path;
+    fuzz_opts.reset = NULL;
+    fuzz_opts.pre_fuzz = NULL;
+    fuzz_opts.fuzz = &fuzz_fork;
+    fuzz_add_qos_target("virtio-net-fork", "virtio-net tx virtqueue",
+            "virtio-net", &opts, &fuzz_opts);
+
+}
+
+fuzz_target_init(register_virtio_net_fuzz_targets);
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* [Qemu-devel] [RFC PATCH v2 17/17] fuzz: Add fuzz accelerator type
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (15 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 16/17] fuzz: Add virtio-net fuzz targets Oleinik, Alexander
@ 2019-08-05  7:11 ` Oleinik, Alexander
  2019-08-05  8:19 ` [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support no-reply
  17 siblings, 0 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-05  7:11 UTC (permalink / raw)
  To: qemu-devel; +Cc: pbonzini, bsd, stefanha, Oleinik, Alexander

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 accel/fuzz.c          | 48 +++++++++++++++++++++++++++++++++++++++++++
 include/sysemu/fuzz.h | 15 ++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 accel/fuzz.c
 create mode 100644 include/sysemu/fuzz.h

diff --git a/accel/fuzz.c b/accel/fuzz.c
new file mode 100644
index 0000000000..9af989aaa1
--- /dev/null
+++ b/accel/fuzz.c
@@ -0,0 +1,48 @@
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "qemu/option.h"
+#include "qemu/config-file.h"
+#include "sysemu/accel.h"
+#include "sysemu/fuzz.h"
+#include "sysemu/cpus.h"
+
+
+static void fuzz_setup_post(MachineState *ms, AccelState *accel)
+{
+}
+
+static int fuzz_init_accel(MachineState *ms)
+{
+    QemuOpts *opts = qemu_opts_create(qemu_find_opts("icount"), NULL, 0,
+                                      &error_abort);
+    qemu_opt_set(opts, "shift", "0", &error_abort);
+    configure_icount(opts, &error_abort);
+    qemu_opts_del(opts);
+    return 0;
+}
+
+static void fuzz_accel_class_init(ObjectClass *oc, void *data)
+{
+    AccelClass *ac = ACCEL_CLASS(oc);
+    ac->name = "fuzz";
+    ac->init_machine = fuzz_init_accel;
+    ac->setup_post = fuzz_setup_post;
+    ac->allowed = &fuzz_allowed;
+}
+
+#define TYPE_FUZZ_ACCEL ACCEL_CLASS_NAME("fuzz")
+
+static const TypeInfo fuzz_accel_type = {
+    .name = TYPE_FUZZ_ACCEL,
+    .parent = TYPE_ACCEL,
+    .class_init = fuzz_accel_class_init,
+};
+
+static void fuzz_type_init(void)
+{
+    type_register_static(&fuzz_accel_type);
+}
+
+type_init(fuzz_type_init);
+
diff --git a/include/sysemu/fuzz.h b/include/sysemu/fuzz.h
new file mode 100644
index 0000000000..09a2a9ffdf
--- /dev/null
+++ b/include/sysemu/fuzz.h
@@ -0,0 +1,15 @@
+#ifndef FUZZ_H
+#define FUZZ_H
+
+bool fuzz_allowed;
+
+static inline bool fuzz_enabled(void)
+{
+    return fuzz_allowed;
+}
+
+bool fuzz_driver(void);
+
+void fuzz_init(const char *fuzz_chrdev, const char *fuzz_log, Error **errp);
+
+#endif
-- 
2.20.1



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init Oleinik, Alexander
@ 2019-08-05  7:43   ` Paolo Bonzini
  2019-08-15 12:41     ` Darren Kenny
  0 siblings, 1 reply; 38+ messages in thread
From: Paolo Bonzini @ 2019-08-05  7:43 UTC (permalink / raw)
  To: Oleinik, Alexander, qemu-devel; +Cc: bsd, stefanha

On 05/08/19 09:11, Oleinik, Alexander wrote:
> Using this, we avoid needing a special case to break out of main(),
> early, when initializing the fuzzer, as we can just call qemu_init.
> There is still a #define around main(), since it otherwise conflicts
> with the libfuzzer main().
> 
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  include/sysemu/sysemu.h |  5 +++++
>  vl.c                    | 25 +++++++++++++++++++++++--
>  2 files changed, 28 insertions(+), 2 deletions(-)
> 
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 984c439ac9..a63d5ccce3 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -184,6 +184,8 @@ QemuOpts *qemu_get_machine_opts(void);
>  
>  bool defaults_enabled(void);
>  
> +int qemu_init(int argc, char **argv, char **envp);
> +
>  extern QemuOptsList qemu_legacy_drive_opts;
>  extern QemuOptsList qemu_common_drive_opts;
>  extern QemuOptsList qemu_drive_opts;
> @@ -197,4 +199,7 @@ extern QemuOptsList qemu_global_opts;
>  extern QemuOptsList qemu_mon_opts;
>  extern QemuOptsList qemu_semihosting_config_opts;
>  
> +#ifdef CONFIG_FUZZ
> +int real_main(int argc, char **argv, char **envp);
> +#endif
>  #endif
> diff --git a/vl.c b/vl.c
> index 130a389712..914bb9b2de 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -130,6 +130,10 @@ int main(int argc, char **argv)
>  #include "sysemu/iothread.h"
>  #include "qemu/guest-random.h"
>  
> +#ifdef CONFIG_FUZZ
> +#include "tests/libqtest.h"
> +#endif

Why is this #include needed?

If you leave out the changes to introduce real_main, the patch can be
committed independent of the rest.  Those can be introduced in patch 2
or even 12 ("Add fuzzer skeleton").

Paolo

>  #define MAX_VIRTIO_CONSOLES 1
>  
>  static const char *data_dir[16];
> @@ -2854,7 +2858,7 @@ static void user_register_global_props(void)
>                        global_init_func, NULL, NULL);
>  }
>  
> -int main(int argc, char **argv, char **envp)
> +int qemu_init(int argc, char **argv, char **envp)
>  {
>      int i;
>      int snapshot, linux_boot;
> @@ -4453,7 +4457,7 @@ int main(int argc, char **argv, char **envp)
>      if (vmstate_dump_file) {
>          /* dump and exit */
>          dump_vmstate_json_to_file(vmstate_dump_file);
> -        return 0;
> +        exit(0);
>      }
>  
>      if (incoming) {
> @@ -4470,6 +4474,23 @@ int main(int argc, char **argv, char **envp)
>      accel_setup_post(current_machine);
>      os_setup_post();
>  
> +    return 0;
> +}
> +#ifdef CONFIG_FUZZ
> +/*
> + * Without this, the compiler complains about all of the unused
> + * cleanup and shutdown() functions
> + */
> +int real_main(int argc, char **argv, char **envp)
> +#else
> +int main(int argc, char **argv, char **envp)
> +#endif
> +{
> +    int ret = qemu_init(argc, argv, envp);
> +    if (ret != 0) {
> +        return ret;
> +    }
> +
>      main_loop();
>  
>      gdbserver_cleanup();
> 



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options Oleinik, Alexander
@ 2019-08-05  7:44   ` Paolo Bonzini
  2019-08-12 22:39   ` Bandan Das
  1 sibling, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2019-08-05  7:44 UTC (permalink / raw)
  To: Oleinik, Alexander, qemu-devel; +Cc: bsd, stefanha

On 05/08/19 09:11, Oleinik, Alexander wrote:
> This adds sanitizer/fuzzer related cflags and adds tests/ to the include
> path. This include change is needed for qos to build, and is normally
> located in tests/Makefile.include, but currently the fuzzer builds from
> the i386-softmmu target, not anything in tests.

Another possibility is to move the libqos and libqtest includes from
tests/ to include/.

Paolo


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized Oleinik, Alexander
@ 2019-08-05  7:44   ` Paolo Bonzini
  2019-08-09  9:04   ` Stefan Hajnoczi
  1 sibling, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2019-08-05  7:44 UTC (permalink / raw)
  To: Oleinik, Alexander, qemu-devel; +Cc: bsd, stefanha

On 05/08/19 09:11, Oleinik, Alexander wrote:
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  util/module.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/util/module.c b/util/module.c
> index 142db7e911..3d4380fd47 100644
> --- a/util/module.c
> +++ b/util/module.c
> @@ -30,6 +30,7 @@ typedef struct ModuleEntry
>  typedef QTAILQ_HEAD(, ModuleEntry) ModuleTypeList;
>  
>  static ModuleTypeList init_type_list[MODULE_INIT_MAX];
> +static bool modules_init_done[MODULE_INIT_MAX];
>  
>  static ModuleTypeList dso_init_list;
>  
> @@ -91,11 +92,17 @@ void module_call_init(module_init_type type)
>      ModuleTypeList *l;
>      ModuleEntry *e;
>  
> +    if (modules_init_done[type]) {
> +        return;
> +    }
> +
>      l = find_type(type);
>  
>      QTAILQ_FOREACH(e, l, node) {
>          e->init();
>      }
> +
> +    modules_init_done[type] = true;
>  }
>  
>  #ifdef CONFIG_MODULES
> 

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type Oleinik, Alexander
@ 2019-08-05  7:50   ` Paolo Bonzini
  2019-08-05 10:46   ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 38+ messages in thread
From: Paolo Bonzini @ 2019-08-05  7:50 UTC (permalink / raw)
  To: Oleinik, Alexander, qemu-devel
  Cc: bsd, Dr. David Alan Gilbert, stefanha, Juan Quintela

On 05/08/19 09:11, Oleinik, Alexander wrote:
> +#ifdef CONFIG_FUZZ
> +#define INCREMENT 10240
> +static ssize_t ram_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
> +        int64_t pos)
> +{
> +    ram_disk *rd = (ram_disk *)opaque;
> +    gsize newsize;
> +    ssize_t total_size = 0;
> +    int i;
> +    if (!rd->base) {
> +        rd->base = g_malloc(INCREMENT);
> +        rd->len = INCREMENT;
> +    }
> +    for (i = 0; i < iovcnt; i++) {
> +        if (pos + iov[i].iov_len >= rd->len) {
> +            newsize = ((pos + iov[i].iov_len) / INCREMENT + 1) * INCREMENT;
> +            rd->base = g_realloc(rd->base, newsize);
> +            rd->len = newsize;
> +        }
> +        memcpy(rd->base + pos, iov[i].iov_base, iov[i].iov_len);
> +        pos += iov[i].iov_len;
> +        total_size += iov[i].iov_len;
> +    }
> +    return total_size;
> +}

A lot of this code can be replaced with GByteArray:
https://developer.gnome.org/glib/stable/glib-Byte-Arrays.html

Since GByteArray is reference counted, you could also easily get rid of
qemu_freopen_ro_ram.  Instead, just close the old QEMUFile and open a
new one.

Paolo

> +static ssize_t ram_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
> +        size_t size)
> +{
> +    ram_disk *rd = (ram_disk *)opaque;
> +    if (pos + size > rd->len) {
> +        if (rd->len - pos >= 0) {
> +            memcpy(buf, rd->base + pos, rd->len - pos);
> +            size = rd->len - pos;
> +        }
> +    } else {
> +        memcpy(buf, rd->base + pos, size);
> +    }
> +    return size;
> +}
> +
> +static int ram_fclose(void *opaque)
> +{
> +    return 0;
> +}
> +
> +static const QEMUFileOps ram_read_ops = {
> +    .get_buffer = ram_get_buffer,
> +    .close =      ram_fclose
> +};
> +
> +static const QEMUFileOps ram_write_ops = {
> +    .writev_buffer = ram_writev_buffer,
> +    .close =      ram_fclose
> +};
> +
> +QEMUFile *qemu_fopen_ram(ram_disk **return_rd)
> +{
> +    ram_disk *rd = g_new0(ram_disk, 1);
> +    *return_rd = rd;
> +    return qemu_fopen_ops(rd, &ram_write_ops);
> +}
> +
> +QEMUFile *qemu_fopen_ro_ram(ram_disk* rd)
> +{
> +    return qemu_fopen_ops(rd, &ram_read_ops);
> +}
> +
> +void qemu_freopen_ro_ram(QEMUFile *f)
> +{
> +    void *rd = f->opaque;
> +    f->bytes_xfer = 0;
> +    f->xfer_limit = 0;
> +    f->last_error = 0;
> +    f->iovcnt = 0;
> +    f->buf_index = 0;
> +    f->buf_size = 0;
> +    f->pos = 0;
> +    f->ops = &ram_read_ops;
> +    f->opaque = rd;
> +    return;
> +}
> +#endif
> diff --git a/migration/qemu-file.h b/migration/qemu-file.h
> index 13baf896bd..7048674f1b 100644
> --- a/migration/qemu-file.h
> +++ b/migration/qemu-file.h
> @@ -177,4 +177,15 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
>  
>  void qemu_put_counted_string(QEMUFile *f, const char *name);
>  
> +#ifdef CONFIG_FUZZ
> +typedef struct ram_disk {
> +    void *base;
> +    gsize len;
> +} ram_disk;
> +
> +QEMUFile *qemu_fopen_ram(ram_disk **rd);
> +QEMUFile *qemu_fopen_ro_ram(ram_disk* rd);
> +void qemu_freopen_ro_ram(QEMUFile *f);
> +#endif
> +
>  #endif
> 



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support
  2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
                   ` (16 preceding siblings ...)
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 17/17] fuzz: Add fuzz accelerator type Oleinik, Alexander
@ 2019-08-05  8:19 ` no-reply
  17 siblings, 0 replies; 38+ messages in thread
From: no-reply @ 2019-08-05  8:19 UTC (permalink / raw)
  To: alxndr; +Cc: pbonzini, bsd, qemu-devel, stefanha, alxndr

Patchew URL: https://patchew.org/QEMU/20190805071038.32146-1-alxndr@bu.edu/



Hi,

This series failed the asan build test. Please find the testing commands and
their output below. If you have Docker installed, you can probably reproduce it
locally.

=== TEST SCRIPT BEGIN ===
#!/bin/bash
make docker-image-fedora V=1 NETWORK=1
time make docker-test-debug@fedora TARGET_LIST=x86_64-softmmu J=14 NETWORK=1
=== TEST SCRIPT END ===

/usr/bin/ld: tests/qos-test.o: in function `qos_set_machines_devices_available':
/tmp/qemu-test/src/tests/qos-test.c:60: undefined reference to `apply_to_qlist'
/usr/bin/ld: /tmp/qemu-test/src/tests/qos-test.c:72: undefined reference to `apply_to_qlist'
clang-8: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [/tmp/qemu-test/src/rules.mak:124: tests/qos-test] Error 1
make: *** Waiting for unfinished jobs....
PASS 1 check-qdict /public/new
---
PASS 32 test-opts-visitor /visitor/opts/range/beyond
PASS 33 test-opts-visitor /visitor/opts/dict/unvisited
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-coroutine -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-coroutine" 
==12227==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-coroutine /basic/no-dangling-access
PASS 2 test-coroutine /basic/lifecycle
==12227==WARNING: ASan is ignoring requested __asan_handle_no_return: stack top: 0x7ffc0b8b1000; bottom 0x7fdb398f8000; size: 0x0020d1fb9000 (140961878016)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189
PASS 3 test-coroutine /basic/yield
---
PASS 12 test-aio /aio/event/flush
PASS 13 test-aio /aio/event/wait/no-flush-cb
PASS 14 test-aio /aio/timer/schedule
==12246==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 15 test-aio /aio/coroutine/queue-chaining
PASS 16 test-aio /aio-gsource/flush
PASS 17 test-aio /aio-gsource/bh/schedule
---
PASS 28 test-aio /aio-gsource/timer/schedule
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-aio-multithread -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-aio-multithread" 
PASS 1 test-aio-multithread /aio/multi/lifecycle
==12252==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 2 test-aio-multithread /aio/multi/schedule
PASS 3 test-aio-multithread /aio/multi/mutex/contended
PASS 4 test-aio-multithread /aio/multi/mutex/handoff
PASS 5 test-aio-multithread /aio/multi/mutex/mcs
PASS 6 test-aio-multithread /aio/multi/mutex/pthread
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-throttle -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-throttle" 
==12288==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-throttle /throttle/leak_bucket
PASS 2 test-throttle /throttle/compute_wait
PASS 3 test-throttle /throttle/init
---
PASS 14 test-throttle /throttle/config/max
PASS 15 test-throttle /throttle/config/iops_size
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-thread-pool -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-thread-pool" 
==12293==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-thread-pool /thread-pool/submit
PASS 2 test-thread-pool /thread-pool/submit-aio
PASS 3 test-thread-pool /thread-pool/submit-co
---
PASS 42 test-hbitmap /hbitmap/next_dirty_area/next_dirty_area_1
PASS 43 test-hbitmap /hbitmap/next_dirty_area/next_dirty_area_4
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-bdrv-drain -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-bdrv-drain" 
==12367==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-bdrv-drain /bdrv-drain/nested
PASS 2 test-bdrv-drain /bdrv-drain/multiparent
PASS 3 test-bdrv-drain /bdrv-drain/set_aio_context
---
PASS 39 test-bdrv-drain /bdrv-drain/detach/driver_cb
PASS 40 test-bdrv-drain /bdrv-drain/attach/drain
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-bdrv-graph-mod -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-bdrv-graph-mod" 
==12407==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-bdrv-graph-mod /bdrv-graph-mod/update-perm-tree
PASS 2 test-bdrv-graph-mod /bdrv-graph-mod/should-update-child
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-blockjob -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-blockjob" 
==12412==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-blockjob /blockjob/ids
PASS 2 test-blockjob /blockjob/cancel/created
PASS 3 test-blockjob /blockjob/cancel/running
---
PASS 7 test-blockjob /blockjob/cancel/pending
PASS 8 test-blockjob /blockjob/cancel/concluded
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-blockjob-txn -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-blockjob-txn" 
==12417==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-blockjob-txn /single/success
PASS 2 test-blockjob-txn /single/failure
PASS 3 test-blockjob-txn /single/cancel
---
PASS 6 test-blockjob-txn /pair/cancel
PASS 7 test-blockjob-txn /pair/fail-cancel-race
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-block-backend -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-block-backend" 
==12422==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-block-backend /block-backend/drain_aio_error
PASS 2 test-block-backend /block-backend/drain_all_aio_error
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-block-iothread -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-block-iothread" 
==12427==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-block-iothread /sync-op/pread
PASS 2 test-block-iothread /sync-op/pwrite
PASS 3 test-block-iothread /sync-op/load_vmstate
---
PASS 15 test-block-iothread /propagate/diamond
PASS 16 test-block-iothread /propagate/mirror
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-image-locking -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-image-locking" 
==12448==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-image-locking /image-locking/basic
PASS 2 test-image-locking /image-locking/set-perm-abort
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-x86-cpuid -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-x86-cpuid" 
---
PASS 1 test-logging /logging/parse_range
PASS 2 test-logging /logging/parse_path
MALLOC_PERTURB_=${MALLOC_PERTURB_:-$(( ${RANDOM:-0} % 255 + 1))}  tests/test-replication -m=quick -k --tap < /dev/null | ./scripts/tap-driver.pl --test-name="test-replication" 
==12865==WARNING: ASan doesn't fully support makecontext/swapcontext functions and may produce false positives in some cases!
PASS 1 test-replication /replication/primary/read
PASS 2 test-replication /replication/primary/write
PASS 3 test-replication /replication/primary/start
---
PASS 6 test-replication /replication/primary/get_error_all
PASS 7 test-replication /replication/secondary/read
PASS 8 test-replication /replication/secondary/write
==12865==WARNING: ASan is ignoring requested __asan_handle_no_return: stack top: 0x7fff78139000; bottom 0x7f04835fc000; size: 0x00faf4b3d000 (1077847248896)
False positive error reports may follow
For details see https://github.com/google/sanitizers/issues/189
PASS 9 test-replication /replication/secondary/start


The full log is available at
http://patchew.org/logs/20190805071038.32146-1-alxndr@bu.edu/testing.asan/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type Oleinik, Alexander
  2019-08-05  7:50   ` Paolo Bonzini
@ 2019-08-05 10:46   ` Dr. David Alan Gilbert
  1 sibling, 0 replies; 38+ messages in thread
From: Dr. David Alan Gilbert @ 2019-08-05 10:46 UTC (permalink / raw)
  To: Oleinik, Alexander; +Cc: pbonzini, bsd, qemu-devel, stefanha, Juan Quintela

* Oleinik, Alexander (alxndr@bu.edu) wrote:

Actually, we've already got a RAM backed QEMU File setup.
You create a 'qio_channel_buffer' and use qemu_fopen_channel_* on it;
see migration/savevm.c:loadvm_handle_cmd_packaged   where we load into
one of these buffersa(bioc)  and then open it as a QEMUFile (packf)

And see migration/migration.c postcopy_start where we create one
(again the channel buffer is bioc, the file is 'fb')

Dave

> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  migration/qemu-file.c | 84 +++++++++++++++++++++++++++++++++++++++++++
>  migration/qemu-file.h | 11 ++++++
>  2 files changed, 95 insertions(+)
> 
> diff --git a/migration/qemu-file.c b/migration/qemu-file.c
> index 0431585502..453e2897d5 100644
> --- a/migration/qemu-file.c
> +++ b/migration/qemu-file.c
> @@ -786,3 +786,87 @@ void qemu_file_set_blocking(QEMUFile *f, bool block)
>          f->ops->set_blocking(f->opaque, block);
>      }
>  }
> +
> +#ifdef CONFIG_FUZZ
> +#define INCREMENT 10240
> +static ssize_t ram_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
> +        int64_t pos)
> +{
> +    ram_disk *rd = (ram_disk *)opaque;
> +    gsize newsize;
> +    ssize_t total_size = 0;
> +    int i;
> +    if (!rd->base) {
> +        rd->base = g_malloc(INCREMENT);
> +        rd->len = INCREMENT;
> +    }
> +    for (i = 0; i < iovcnt; i++) {
> +        if (pos + iov[i].iov_len >= rd->len) {
> +            newsize = ((pos + iov[i].iov_len) / INCREMENT + 1) * INCREMENT;
> +            rd->base = g_realloc(rd->base, newsize);
> +            rd->len = newsize;
> +        }
> +        memcpy(rd->base + pos, iov[i].iov_base, iov[i].iov_len);
> +        pos += iov[i].iov_len;
> +        total_size += iov[i].iov_len;
> +    }
> +    return total_size;
> +}
> +
> +static ssize_t ram_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
> +        size_t size)
> +{
> +    ram_disk *rd = (ram_disk *)opaque;
> +    if (pos + size > rd->len) {
> +        if (rd->len - pos >= 0) {
> +            memcpy(buf, rd->base + pos, rd->len - pos);
> +            size = rd->len - pos;
> +        }
> +    } else {
> +        memcpy(buf, rd->base + pos, size);
> +    }
> +    return size;
> +}
> +
> +static int ram_fclose(void *opaque)
> +{
> +    return 0;
> +}
> +
> +static const QEMUFileOps ram_read_ops = {
> +    .get_buffer = ram_get_buffer,
> +    .close =      ram_fclose
> +};
> +
> +static const QEMUFileOps ram_write_ops = {
> +    .writev_buffer = ram_writev_buffer,
> +    .close =      ram_fclose
> +};
> +
> +QEMUFile *qemu_fopen_ram(ram_disk **return_rd)
> +{
> +    ram_disk *rd = g_new0(ram_disk, 1);
> +    *return_rd = rd;
> +    return qemu_fopen_ops(rd, &ram_write_ops);
> +}
> +
> +QEMUFile *qemu_fopen_ro_ram(ram_disk* rd)
> +{
> +    return qemu_fopen_ops(rd, &ram_read_ops);
> +}
> +
> +void qemu_freopen_ro_ram(QEMUFile *f)
> +{
> +    void *rd = f->opaque;
> +    f->bytes_xfer = 0;
> +    f->xfer_limit = 0;
> +    f->last_error = 0;
> +    f->iovcnt = 0;
> +    f->buf_index = 0;
> +    f->buf_size = 0;
> +    f->pos = 0;
> +    f->ops = &ram_read_ops;
> +    f->opaque = rd;
> +    return;
> +}
> +#endif
> diff --git a/migration/qemu-file.h b/migration/qemu-file.h
> index 13baf896bd..7048674f1b 100644
> --- a/migration/qemu-file.h
> +++ b/migration/qemu-file.h
> @@ -177,4 +177,15 @@ size_t ram_control_save_page(QEMUFile *f, ram_addr_t block_offset,
>  
>  void qemu_put_counted_string(QEMUFile *f, const char *name);
>  
> +#ifdef CONFIG_FUZZ
> +typedef struct ram_disk {
> +    void *base;
> +    gsize len;
> +} ram_disk;
> +
> +QEMUFile *qemu_fopen_ram(ram_disk **rd);
> +QEMUFile *qemu_fopen_ro_ram(ram_disk* rd);
> +void qemu_freopen_ro_ram(QEMUFile *f);
> +#endif
> +
>  #endif
> -- 
> 2.20.1
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 08/17] fuzz: Export the qemu_savevm_live_state function
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 08/17] fuzz: Export the qemu_savevm_live_state function Oleinik, Alexander
@ 2019-08-05 10:54   ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 38+ messages in thread
From: Dr. David Alan Gilbert @ 2019-08-05 10:54 UTC (permalink / raw)
  To: Oleinik, Alexander; +Cc: pbonzini, bsd, qemu-devel, stefanha, Juan Quintela

* Oleinik, Alexander (alxndr@bu.edu) wrote:
> Skip the header when saving device state, as the header isn't handled by
> qemu_load_device_state
> 
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  migration/savevm.c | 9 +++++++--
>  migration/savevm.h | 2 ++
>  2 files changed, 9 insertions(+), 2 deletions(-)
> 
> diff --git a/migration/savevm.c b/migration/savevm.c
> index 79ed44d475..5eac36e6ca 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -1405,7 +1405,7 @@ void qemu_savevm_state_cleanup(void)
>      }
>  }
>  
> -static int qemu_savevm_state(QEMUFile *f, Error **errp)
> +int qemu_savevm_state(QEMUFile *f, Error **errp)
>  {
>      int ret;
>      MigrationState *ms = migrate_get_current();
> @@ -1471,11 +1471,16 @@ void qemu_savevm_live_state(QEMUFile *f)
>  int qemu_save_device_state(QEMUFile *f)
>  {
>      SaveStateEntry *se;
> -
> +    /*
> +     * qemu_load_device_state doesn't load the header. Either skip writing the
> +     * header or seek forward in the file, prior to loading device state
> +     */
> +#ifndef CONFIG_FUZZ
>      if (!migration_in_colo_state()) {
>          qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
>          qemu_put_be32(f, QEMU_VM_FILE_VERSION);
>      }
> +#endif

I'd prefer if you just added a ', bool save_header' to the parameters
and then replace the '!migration_in_colo_state()' by 'save_header'

It's only called from two places at the moment,
'qmp_xen_save_devices_state' where I think it's always 'true'
and 'colo_do_checkpoint_transaction' where I think it's always false.

Dave

>      cpu_synchronize_all_states();
>  
>      QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
> diff --git a/migration/savevm.h b/migration/savevm.h
> index 51a4b9caa8..5405215cb4 100644
> --- a/migration/savevm.h
> +++ b/migration/savevm.h
> @@ -64,4 +64,6 @@ void qemu_loadvm_state_cleanup(void);
>  int qemu_loadvm_state_main(QEMUFile *f, MigrationIncomingState *mis);
>  int qemu_load_device_state(QEMUFile *f);
>  
> +int qemu_savevm_state(QEMUFile *f, Error **errp);
> +
>  #endif
> -- 
> 2.20.1
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 03/17] fuzz: Keep memory mapped for fork-based fuzzer
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 03/17] fuzz: Keep memory mapped for fork-based fuzzer Oleinik, Alexander
@ 2019-08-09  9:01   ` Stefan Hajnoczi
  0 siblings, 0 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:01 UTC (permalink / raw)
  To: Oleinik, Alexander; +Cc: pbonzini, bsd, qemu-devel, stefanha, Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 347 bytes --]

On Mon, Aug 05, 2019 at 07:11:04AM +0000, Oleinik, Alexander wrote:
> Otherwise, the RAM is unmapped from the child-processes, which breaks
> any fuzz tests relying on DMA.
> 
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  exec.c | 2 ++
>  1 file changed, 2 insertions(+)

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized Oleinik, Alexander
  2019-08-05  7:44   ` Paolo Bonzini
@ 2019-08-09  9:04   ` Stefan Hajnoczi
  2019-08-13 18:53     ` Oleinik, Alexander
  1 sibling, 1 reply; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:04 UTC (permalink / raw)
  To: Oleinik, Alexander; +Cc: pbonzini, bsd, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 342 bytes --]

On Mon, Aug 05, 2019 at 07:11:05AM +0000, Oleinik, Alexander wrote:
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  util/module.c | 7 +++++++
>  1 file changed, 7 insertions(+)

Why is this necessary?  Existing callers only invoke this function once
for each type.

Please include justification in the commit description.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 06/17] fuzz: Add FUZZ_TARGET module type
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 06/17] fuzz: Add FUZZ_TARGET module type Oleinik, Alexander
@ 2019-08-09  9:07   ` Stefan Hajnoczi
  0 siblings, 0 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:07 UTC (permalink / raw)
  To: Oleinik, Alexander; +Cc: pbonzini, bsd, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 261 bytes --]

On Mon, Aug 05, 2019 at 07:11:07AM +0000, Oleinik, Alexander wrote:
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  include/qemu/module.h | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 05/17] fuzz: Add direct receive function for qtest server
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 05/17] fuzz: Add direct receive function for qtest server Oleinik, Alexander
@ 2019-08-09  9:23   ` Stefan Hajnoczi
  0 siblings, 0 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:23 UTC (permalink / raw)
  To: Oleinik, Alexander
  Cc: Laurent Vivier, Thomas Huth, qemu-devel, bsd, stefanha, pbonzini

[-- Attachment #1: Type: text/plain, Size: 1442 bytes --]

On Mon, Aug 05, 2019 at 07:11:06AM +0000, Oleinik, Alexander wrote:
> The direct receive function qtest_server_recv is directly invoked by the
> qtest client, when the server and client exist within the same process.
> 
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  include/sysemu/qtest.h |  4 ++++
>  qtest.c                | 14 ++++++++++++++
>  2 files changed, 18 insertions(+)

qtest.c has two parts:
1. The qtest protocol handler
2. The chardev/qtest_init() code

This patch uses #ifdefs to leave most of the code unmodified, but this
is hacky since we need to pass around a NULL CharBackend pointer in
order to reuse the code.  There is a danger that someone will modify the
core code and operate on chr not knowing it will break fuzzing.

A cleaner approach is to refactor the qtest protocol handler code to be
transport-independent with a send(void *opaque, const char *str, size_t
len) function pointer provided by the actual transport.  That way the
core code doesn't know about CharBackend and can never accidentally
touch it.

One way of doing this is to introduce a global qtest_send() function
pointer and pass a void *opaque value through the core qtest protocol
handler code.

If you introduce a separate qtest-fuzz.c file then no #ifdefs are
necessary because the conditional compilation can be performed by
CONFIG_FUZZ in Makefile.objs:

  obj-$(CONFIG_FUZZ) += qtest-fuzz.o

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 09/17] fuzz: hardcode needed objects into i386 target
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 09/17] fuzz: hardcode needed objects into i386 target Oleinik, Alexander
@ 2019-08-09  9:33   ` Stefan Hajnoczi
  2019-08-16 12:51     ` Darren Kenny
  0 siblings, 1 reply; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:33 UTC (permalink / raw)
  To: Oleinik, Alexander
  Cc: Eduardo Habkost, qemu-devel, bsd, stefanha, pbonzini, Richard Henderson

[-- Attachment #1: Type: text/plain, Size: 2319 bytes --]

On Mon, Aug 05, 2019 at 07:11:10AM +0000, Oleinik, Alexander wrote:
> Temporary solution until there is a better build solution for fuzzers in
> tests/Makefile.include
> 
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  target/i386/Makefile.objs | 20 ++++++++++++++++++++
>  1 file changed, 20 insertions(+)
> 
> diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs
> index 48e0c28434..1b8976c0a6 100644
> --- a/target/i386/Makefile.objs
> +++ b/target/i386/Makefile.objs
> @@ -18,5 +18,25 @@ endif
>  obj-$(CONFIG_HVF) += hvf/
>  obj-$(CONFIG_WHPX) += whpx-all.o
>  endif
> +
> +# Need to link against target, qtest and qos.. Just list everything here, until
> +# I find a better way to integrate into the build system

There are two similar solutions:

1. Use tests/Makefile.include, e.g. libqos-obj-y.
2. Build a .a archive file in tests/Makefile.include and link against it.

In both cases it is no longer necessary to list ../../tests/ object
files in target/i386/Makefile.objs.

> +ifeq ($(CONFIG_FUZZ),y)

ifeq isn't necessary since obj-$(CONFIG_FUZZ) is already conditional
below.

> +obj-$(CONFIG_FUZZ) += ../../accel/fuzz.o ../../tests/libqos/qos_external.o
> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/fuzz.o ../../tests/fuzz/fuzzer_hooks.o
> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/virtio-net-fuzz.o
> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/snapshotting.o
> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/qtest_fuzz.o
> +obj-$(CONFIG_FUZZ) += ../../tests/libqtest.o
> +obj-$(CONFIG_FUZZ) += ../../tests/libqos/qgraph.o ../../tests/libqos/libqos.o
> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/qos_fuzz.o ../../tests/fuzz/qos_helpers.o
> +obj-$(CONFIG_FUZZ) +=  ../../tests/libqos/malloc.o ../../tests/libqos/pci-pc.o \
> +	../../tests/libqos/virtio-pci.o ../../tests/libqos/malloc-pc.o \
> +	../../tests/libqos/libqos-pc.o ../../tests/libqos/fw_cfg.o \
> +	../../tests/libqos/e1000e.o ../../tests/libqos/pci.o \
> +	../../tests/libqos/pci-pc.o ../../tests/libqos/virtio.o \
> +	../../tests/libqos/virtio-net.o ../../tests/libqos/x86_64_pc-machine.o

I see filenames here that are not in the tree yet at this point in the
patch series.  Please make sure that QEMU builds at each point in the
patch series so that git-bisect(1) works.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 10/17] fuzz: qtest client directly interacts with server
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 10/17] fuzz: qtest client directly interacts with server Oleinik, Alexander
@ 2019-08-09  9:37   ` Stefan Hajnoczi
  0 siblings, 0 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:37 UTC (permalink / raw)
  To: Oleinik, Alexander
  Cc: Laurent Vivier, Thomas Huth, qemu-devel, bsd, stefanha, pbonzini

[-- Attachment #1: Type: text/plain, Size: 773 bytes --]

On Mon, Aug 05, 2019 at 07:11:11AM +0000, Oleinik, Alexander wrote:
> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> ---
>  tests/libqtest.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++--
>  tests/libqtest.h |  6 +++++
>  2 files changed, 65 insertions(+), 2 deletions(-)

Please refactor the code instead of adding #ifdefs.  Most of the code
doesn't care whether it is communicating over a socket or in-process.

> @@ -317,6 +323,21 @@ QTestState *qtest_initf(const char *fmt, ...)
>      return s;
>  }
>  
> +#ifdef CONFIG_FUZZ
> +QTestState *qtest_fuzz_init(const char *extra_args, int *sock_fd)

This isn't really specific to fuzzing.  It's just an in-process qtest
client for QEMU.  Please name it qtest_inproc_client_init() or similar.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 12/17] fuzz: Add fuzzer skeleton
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 12/17] fuzz: Add fuzzer skeleton Oleinik, Alexander
@ 2019-08-09  9:43   ` Stefan Hajnoczi
  0 siblings, 0 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:43 UTC (permalink / raw)
  To: Oleinik, Alexander; +Cc: pbonzini, bsd, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 2300 bytes --]

On Mon, Aug 05, 2019 at 07:11:13AM +0000, Oleinik, Alexander wrote:
> diff --git a/tests/fuzz/fuzz.c b/tests/fuzz/fuzz.c
> new file mode 100644
> index 0000000000..9e03e15d7b
> --- /dev/null
> +++ b/tests/fuzz/fuzz.c
> @@ -0,0 +1,245 @@
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/iov.h"
> +#include "exec/memory.h"
> +#include "exec/address-spaces.h"
> +#include "migration/qemu-file.h"
> +
> +#include "migration/qemu-file.h"
> +#include "migration/global_state.h"
> +#include "migration/savevm.h"
> +#include "tests/libqtest.h"
> +#include "migration/migration.h"
> +#include "fuzz.h"
> +#include "tests/libqos/qgraph.h"
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <linux/userfaultfd.h>
> +#include <poll.h>
> +#include <pthread.h>
> +#include <sys/syscall.h>
> +#include <sys/types.h>
> +#include <sys/ioctl.h>

There's a lot of stuff going on here, the qemu-file.h include is
duplicated, system headers should be before application headers (see
./HACKING), and some of the headers aren't used.  Please clean these
includes up.

> +/* Save the entire vm state including RAM */
> +void save_vm_state(void)
> +{
> +    writefile = qemu_fopen_ram(&rd);
> +    vm_stop(RUN_STATE_SAVE_VM);
> +    global_state_store();
> +    qemu_savevm_state(writefile, NULL);
> +    qemu_fflush(writefile);
> +    ramfile = qemu_fopen_ro_ram(rd);
> +}
> +
> +/* Reset state by rebooting */
> +void reboot()

Please use void foo(void) in C.  Unlike C++, where void foo() is
equivalent to void foo(void), void foo() means that the arguments are
unspecified and not checked by the compiler!

> +void qtest_setup()
> +{
> +    s = qtest_fuzz_init(NULL, NULL);
> +    global_qtest = s;

Is global_qtest used by any fuzz tests?  Thomas Huth (qtest maintainer)
wants to get rid of it soon.  Perhaps it's possible to avoid it in fuzz
tests so it never needs to be introduced.

> diff --git a/tests/fuzz/fuzz.h b/tests/fuzz/fuzz.h
> new file mode 100644
> index 0000000000..46ec38d4ea
> --- /dev/null
> +++ b/tests/fuzz/fuzz.h
> @@ -0,0 +1,70 @@
> +#ifndef FUZZER_H_
> +#define FUZZER_H_

There are a bunch of global variables in this file.  It's not clear to
me yet at this point in the patch series that they need to be global...
Have you checked that they need to be global?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 14/17] fuzz: Add forking support to the fuzzer
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 14/17] fuzz: Add forking " Oleinik, Alexander
@ 2019-08-09  9:46   ` Stefan Hajnoczi
  0 siblings, 0 replies; 38+ messages in thread
From: Stefan Hajnoczi @ 2019-08-09  9:46 UTC (permalink / raw)
  To: Oleinik, Alexander; +Cc: pbonzini, bsd, qemu-devel, stefanha

[-- Attachment #1: Type: text/plain, Size: 551 bytes --]

On Mon, Aug 05, 2019 at 07:11:15AM +0000, Oleinik, Alexander wrote:
> +void *counter_shm;
> +size_t feature_shm_len;
> +uintptr_t feature_shm;
> +size_t offset;
> +
> +typedef struct CoverageRegion {
> +    uint8_t *start;
> +    size_t length;
> +    bool store; /* Set this if it needs to be copied to the forked process */
> +} CoverageRegion;
> +
> +CoverageRegion regions[10];
> +int region_index;
> +

The global variable names in this file are likely to cause naming
collisions.  Do they need to be global?  If yes, please prefix with
"fuzz_".

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options
  2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options Oleinik, Alexander
  2019-08-05  7:44   ` Paolo Bonzini
@ 2019-08-12 22:39   ` Bandan Das
  2019-08-13 18:46     ` Oleinik, Alexander
  1 sibling, 1 reply; 38+ messages in thread
From: Bandan Das @ 2019-08-12 22:39 UTC (permalink / raw)
  To: Oleinik\, Alexander; +Cc: pbonzini, qemu-devel, stefanha

"Oleinik, Alexander" <alxndr@bu.edu> writes:
...
>  if test "$supported_cpu" = "no"; then
>      echo
> @@ -7306,6 +7310,17 @@ fi
>  if test "$sheepdog" = "yes" ; then
>    echo "CONFIG_SHEEPDOG=y" >> $config_host_mak
>  fi
> +if test "$fuzzing" = "yes" ; then
> +  QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize=fuzzer,address  -fprofile-instr-generate"
> +  QEMU_CFLAGS="$QEMU_CFLAGS -fprofile-instr-generate -fcoverage-mapping"

What is the purpose of -fprofile-instr-generate ? Coverage info ? (Listed twice above)

Bandan

> +  QEMU_LDFLAGS="$LDFLAGS -fsanitize=fuzzer,address"
> +
> +  # Add tests/ to include path, since this is done in tests/Makefile.include,
> +  # and required for QOS objects to build. This can be removed if/when the
> +  # fuzzer is compiled using rules in tests/Makefile.include
> +  QEMU_INCLUDES="-iquote \$(SRC_PATH)/tests $QEMU_INCLUDES"
> +  echo "CONFIG_FUZZ=y" >> $config_host_mak
> +fi
>  
>  if test "$tcg_interpreter" = "yes"; then
>    QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options
  2019-08-12 22:39   ` Bandan Das
@ 2019-08-13 18:46     ` Oleinik, Alexander
  0 siblings, 0 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-13 18:46 UTC (permalink / raw)
  To: bsd; +Cc: pbonzini, qemu-devel, stefanha

On Mon, 2019-08-12 at 18:39 -0400, Bandan Das wrote:
> "Oleinik, Alexander" <alxndr@bu.edu> writes:
> ...
> >  if test "$supported_cpu" = "no"; then
> >      echo
> > @@ -7306,6 +7310,17 @@ fi
> >  if test "$sheepdog" = "yes" ; then
> >    echo "CONFIG_SHEEPDOG=y" >> $config_host_mak
> >  fi
> > +if test "$fuzzing" = "yes" ; then
> > +  QEMU_CFLAGS="$QEMU_CFLAGS -fsanitize=fuzzer,address  -fprofile-
> > instr-generate"
> > +  QEMU_CFLAGS="$QEMU_CFLAGS -fprofile-instr-generate -fcoverage-
> > mapping"
> 
> What is the purpose of -fprofile-instr-generate ? Coverage info ?
> (Listed twice above)
Yes, it's for coverage info. I'll fix it so it is only listed once.

> Bandan
> 
> > +  QEMU_LDFLAGS="$LDFLAGS -fsanitize=fuzzer,address"
> > +
> > +  # Add tests/ to include path, since this is done in
> > tests/Makefile.include,
> > +  # and required for QOS objects to build. This can be removed
> > if/when the
> > +  # fuzzer is compiled using rules in tests/Makefile.include
> > +  QEMU_INCLUDES="-iquote \$(SRC_PATH)/tests $QEMU_INCLUDES"
> > +  echo "CONFIG_FUZZ=y" >> $config_host_mak
> > +fi
> >  
> >  if test "$tcg_interpreter" = "yes"; then
> >    QEMU_INCLUDES="-iquote \$(SRC_PATH)/tcg/tci $QEMU_INCLUDES"


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized
  2019-08-09  9:04   ` Stefan Hajnoczi
@ 2019-08-13 18:53     ` Oleinik, Alexander
  0 siblings, 0 replies; 38+ messages in thread
From: Oleinik, Alexander @ 2019-08-13 18:53 UTC (permalink / raw)
  To: stefanha; +Cc: pbonzini, bsd, qemu-devel, stefanha

On Fri, 2019-08-09 at 10:04 +0100, Stefan Hajnoczi wrote:
> On Mon, Aug 05, 2019 at 07:11:05AM +0000, Oleinik, Alexander wrote:
> > Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
> > ---
> >  util/module.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> 
> Why is this necessary?  Existing callers only invoke this function
> once
> for each type.
This was suggested by Paolo in Message-ID:
fad9d12a-39df-e2fa-064b-5132add9daff@redhat.com

I need to initialize the QOS module in the fuzzer main to identify the
qemu arguments, prior to running vl.c:main.
> Please include justification in the commit description.
Will do
> Stefan


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init
  2019-08-05  7:43   ` Paolo Bonzini
@ 2019-08-15 12:41     ` Darren Kenny
  0 siblings, 0 replies; 38+ messages in thread
From: Darren Kenny @ 2019-08-15 12:41 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: Oleinik, Alexander, bsd, qemu-devel, stefanha

On Mon, Aug 05, 2019 at 09:43:06AM +0200, Paolo Bonzini wrote:
>On 05/08/19 09:11, Oleinik, Alexander wrote:
>> Using this, we avoid needing a special case to break out of main(),
>> early, when initializing the fuzzer, as we can just call qemu_init.
>> There is still a #define around main(), since it otherwise conflicts
>> with the libfuzzer main().
>>
>> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
>> ---
>>  include/sysemu/sysemu.h |  5 +++++
>>  vl.c                    | 25 +++++++++++++++++++++++--
>>  2 files changed, 28 insertions(+), 2 deletions(-)
>>
>> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
>> index 984c439ac9..a63d5ccce3 100644
>> --- a/include/sysemu/sysemu.h
>> +++ b/include/sysemu/sysemu.h
>> @@ -184,6 +184,8 @@ QemuOpts *qemu_get_machine_opts(void);
>>
>>  bool defaults_enabled(void);
>>
>> +int qemu_init(int argc, char **argv, char **envp);
>> +
>>  extern QemuOptsList qemu_legacy_drive_opts;
>>  extern QemuOptsList qemu_common_drive_opts;
>>  extern QemuOptsList qemu_drive_opts;
>> @@ -197,4 +199,7 @@ extern QemuOptsList qemu_global_opts;
>>  extern QemuOptsList qemu_mon_opts;
>>  extern QemuOptsList qemu_semihosting_config_opts;
>>
>> +#ifdef CONFIG_FUZZ
>> +int real_main(int argc, char **argv, char **envp);
>> +#endif
>>  #endif
>> diff --git a/vl.c b/vl.c
>> index 130a389712..914bb9b2de 100644
>> --- a/vl.c
>> +++ b/vl.c
>> @@ -130,6 +130,10 @@ int main(int argc, char **argv)
>>  #include "sysemu/iothread.h"
>>  #include "qemu/guest-random.h"
>>
>> +#ifdef CONFIG_FUZZ
>> +#include "tests/libqtest.h"
>> +#endif
>
>Why is this #include needed?
>
>If you leave out the changes to introduce real_main, the patch can be
>committed independent of the rest.  Those can be introduced in patch 2
>or even 12 ("Add fuzzer skeleton").

The build actually fails for me due to this include, because it has it's own
and different declaration of qtest_init:

  In file included from vl.c:134:
  .../qemu-upstream-libfuzz/./tests/libqtest.h:57:13: error: conflicting types for 'qtest_init'
  QTestState *qtest_init(const char *extra_args);
              ^
  .../qemu-upstream-libfuzz/include/sysemu/qtest.h:27:6: note: previous declaration is here
  void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
       ^
  In file included from vl.c:134:
  .../qemu-upstream-libfuzz/./tests/libqtest.h:640:35: error: too few arguments to function call, expected 3, have 1
      global_qtest = qtest_init(args);
                     ~~~~~~~~~~     ^
  .../qemu-upstream-libfuzz/include/sysemu/qtest.h:27:1: note: 'qtest_init' declared here
  void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
  ^
  2 errors generated.

(It's probably a separate issue as to why there are 2 functions with
the same name, are not static and have different signatures in the
first place)

Thanks,

Darren.



^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [Qemu-devel] [RFC PATCH v2 09/17] fuzz: hardcode needed objects into i386 target
  2019-08-09  9:33   ` Stefan Hajnoczi
@ 2019-08-16 12:51     ` Darren Kenny
  0 siblings, 0 replies; 38+ messages in thread
From: Darren Kenny @ 2019-08-16 12:51 UTC (permalink / raw)
  To: Oleinik, Alexander
  Cc: Eduardo Habkost, qemu-devel, bsd, stefanha, pbonzini, Richard Henderson

Hi Alexander,

On Fri, Aug 09, 2019 at 10:33:59AM +0100, Stefan Hajnoczi wrote:
>On Mon, Aug 05, 2019 at 07:11:10AM +0000, Oleinik, Alexander wrote:
>> Temporary solution until there is a better build solution for fuzzers in
>> tests/Makefile.include
>>
>> Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
>> ---
>>  target/i386/Makefile.objs | 20 ++++++++++++++++++++
>>  1 file changed, 20 insertions(+)
>>
>> diff --git a/target/i386/Makefile.objs b/target/i386/Makefile.objs
>> index 48e0c28434..1b8976c0a6 100644
>> --- a/target/i386/Makefile.objs
>> +++ b/target/i386/Makefile.objs
>> @@ -18,5 +18,25 @@ endif
>>  obj-$(CONFIG_HVF) += hvf/
>>  obj-$(CONFIG_WHPX) += whpx-all.o
>>  endif
>> +
>> +# Need to link against target, qtest and qos.. Just list everything here, until
>> +# I find a better way to integrate into the build system
>
>There are two similar solutions:
>
>1. Use tests/Makefile.include, e.g. libqos-obj-y.
>2. Build a .a archive file in tests/Makefile.include and link against it.
>
>In both cases it is no longer necessary to list ../../tests/ object
>files in target/i386/Makefile.objs.
>
>> +ifeq ($(CONFIG_FUZZ),y)
>
>ifeq isn't necessary since obj-$(CONFIG_FUZZ) is already conditional
>below.
>
>> +obj-$(CONFIG_FUZZ) += ../../accel/fuzz.o ../../tests/libqos/qos_external.o
>> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/fuzz.o ../../tests/fuzz/fuzzer_hooks.o
>> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/virtio-net-fuzz.o
>> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/snapshotting.o
>> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/qtest_fuzz.o
>> +obj-$(CONFIG_FUZZ) += ../../tests/libqtest.o
>> +obj-$(CONFIG_FUZZ) += ../../tests/libqos/qgraph.o ../../tests/libqos/libqos.o
>> +obj-$(CONFIG_FUZZ) += ../../tests/fuzz/qos_fuzz.o ../../tests/fuzz/qos_helpers.o
>> +obj-$(CONFIG_FUZZ) +=  ../../tests/libqos/malloc.o ../../tests/libqos/pci-pc.o \
>> +	../../tests/libqos/virtio-pci.o ../../tests/libqos/malloc-pc.o \
>> +	../../tests/libqos/libqos-pc.o ../../tests/libqos/fw_cfg.o \
>> +	../../tests/libqos/e1000e.o ../../tests/libqos/pci.o \
>> +	../../tests/libqos/pci-pc.o ../../tests/libqos/virtio.o \
>> +	../../tests/libqos/virtio-net.o ../../tests/libqos/x86_64_pc-machine.o
>
>I see filenames here that are not in the tree yet at this point in the
>patch series.  Please make sure that QEMU builds at each point in the
>patch series so that git-bisect(1) works.

Even after applying the series I'm not seeing any snapshotting.[ch]
files - so virtio-net-fuzz.c fails to build too because of the
missing header file.

But overall, I'm finding lots of failures when building the series,
not just at any specific point in time, so it would be worth at
least doing a clean checkout of the tree and applying the patches,
and doing a full build, before sending out the next set, to be sure
that they are complete.

Thanks,

Darren.



^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, back to index

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-05  7:11 [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support Oleinik, Alexander
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 01/17] fuzz: Move initialization from main to qemu_init Oleinik, Alexander
2019-08-05  7:43   ` Paolo Bonzini
2019-08-15 12:41     ` Darren Kenny
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 02/17] fuzz: Add fuzzer configure options Oleinik, Alexander
2019-08-05  7:44   ` Paolo Bonzini
2019-08-12 22:39   ` Bandan Das
2019-08-13 18:46     ` Oleinik, Alexander
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 03/17] fuzz: Keep memory mapped for fork-based fuzzer Oleinik, Alexander
2019-08-09  9:01   ` Stefan Hajnoczi
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 04/17] fuzz: Skip modules that were already initialized Oleinik, Alexander
2019-08-05  7:44   ` Paolo Bonzini
2019-08-09  9:04   ` Stefan Hajnoczi
2019-08-13 18:53     ` Oleinik, Alexander
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 05/17] fuzz: Add direct receive function for qtest server Oleinik, Alexander
2019-08-09  9:23   ` Stefan Hajnoczi
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 06/17] fuzz: Add FUZZ_TARGET module type Oleinik, Alexander
2019-08-09  9:07   ` Stefan Hajnoczi
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 07/17] fuzz: Add ramfile qemu-file type Oleinik, Alexander
2019-08-05  7:50   ` Paolo Bonzini
2019-08-05 10:46   ` Dr. David Alan Gilbert
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 08/17] fuzz: Export the qemu_savevm_live_state function Oleinik, Alexander
2019-08-05 10:54   ` Dr. David Alan Gilbert
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 09/17] fuzz: hardcode needed objects into i386 target Oleinik, Alexander
2019-08-09  9:33   ` Stefan Hajnoczi
2019-08-16 12:51     ` Darren Kenny
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 10/17] fuzz: qtest client directly interacts with server Oleinik, Alexander
2019-08-09  9:37   ` Stefan Hajnoczi
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 11/17] fuzz: Move useful qos functions to separate object Oleinik, Alexander
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 12/17] fuzz: Add fuzzer skeleton Oleinik, Alexander
2019-08-09  9:43   ` Stefan Hajnoczi
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 13/17] fuzz: Add libqos support to the fuzzer Oleinik, Alexander
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 14/17] fuzz: Add forking " Oleinik, Alexander
2019-08-09  9:46   ` Stefan Hajnoczi
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 15/17] fuzz: Add general qtest fuzz-target Oleinik, Alexander
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 16/17] fuzz: Add virtio-net fuzz targets Oleinik, Alexander
2019-08-05  7:11 ` [Qemu-devel] [RFC PATCH v2 17/17] fuzz: Add fuzz accelerator type Oleinik, Alexander
2019-08-05  8:19 ` [Qemu-devel] [RFC PATCH v2 00/17] Add virtual device fuzzing support no-reply

QEMU-Devel Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/qemu-devel/0 qemu-devel/git/0.git
	git clone --mirror https://lore.kernel.org/qemu-devel/1 qemu-devel/git/1.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 qemu-devel qemu-devel/ https://lore.kernel.org/qemu-devel \
		qemu-devel@nongnu.org qemu-devel@archiver.kernel.org
	public-inbox-index qemu-devel


Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.nongnu.qemu-devel


AGPL code for this site: git clone https://public-inbox.org/ public-inbox