All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Oleinik, Alexander" <alxndr@bu.edu>
To: "qemu-devel@nongnu.org" <qemu-devel@nongnu.org>
Cc: "pbonzini@redhat.com" <pbonzini@redhat.com>,
	"bsd@redhat.com" <bsd@redhat.com>,
	"superirishdonkey@gmail.com" <superirishdonkey@gmail.com>,
	"stefanha@redhat.com" <stefanha@redhat.com>,
	"Oleinik,  Alexander" <alxndr@bu.edu>
Subject: [Qemu-devel] [RFC 17/19] fuzz: add general qtest fuzz target
Date: Thu, 25 Jul 2019 03:23:59 +0000	[thread overview]
Message-ID: <20190725032321.12721-18-alxndr@bu.edu> (raw)
In-Reply-To: <20190725032321.12721-1-alxndr@bu.edu>

These fuzz targets perform a range of qtest operations over mmio and
port i/o addresses mapped to devices.

Signed-off-by: Alexander Oleinik <alxndr@bu.edu>
---
 tests/fuzz/qtest_fuzz.c | 261 ++++++++++++++++++++++++++++++++++++++++
 tests/fuzz/qtest_fuzz.h |  38 ++++++
 2 files changed, 299 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..6d6670838d
--- /dev/null
+++ b/tests/fuzz/qtest_fuzz.c
@@ -0,0 +1,261 @@
+#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) {
+    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;
+    if(addr>=0xae00 && addr<=0xae13) // PCI Hotplug
+        return 0;
+    if(addr>=0xaf00 && addr<=0xaf1f) // CPU Hotplug
+        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) {
+    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 init_fork(void) {
+    qos_init_path();
+}
+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,
+    };
+    fuzz_add_qos_target("qtest-fuzz", "fuzz qtest commands and a dma buffer. Reset device state for each run",
+            "e1000e", &opts, &qos_setup, &qos_init_path, &save_vm_state, &load_vm_state,
+            NULL, &qtest_fuzz, NULL);
+    fuzz_add_qos_target("qtest-fork-fuzz", "fuzz qtest commands and a dma buffer. Use COW/forking to reset state",
+            "e1000e", &opts, &fork_pre_main, NULL, &init_fork, NULL,
+            NULL, &fuzz_fork, NULL);
+
+    GString *cmd_line = g_string_new("qemu-system-i386 -display none -machine accel=fuzz -m 3"); 
+    wordexp_t result;
+    wordexp (cmd_line->str, &result, 0);
+    qtest_argc = result.we_wordc;
+    qtest_argv = result.we_wordv;
+    g_string_free(cmd_line, true);
+}
+
+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..bf472954e7
--- /dev/null
+++ b/tests/fuzz/qtest_fuzz.h
@@ -0,0 +1,38 @@
+#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



  parent reply	other threads:[~2019-07-25  3:27 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-25  3:23 [Qemu-devel] [RFC 00/19] Add virtual device fuzzing support Oleinik, Alexander
2019-07-25  3:23 ` [Qemu-devel] [RFC 01/19] fuzz: add configure option and linker objects Oleinik, Alexander
2019-07-25  9:39   ` Paolo Bonzini
2019-07-25  3:23 ` [Qemu-devel] [RFC 02/19] fuzz: add FUZZ_TARGET type to qemu module system Oleinik, Alexander
2019-07-26 12:32   ` Stefan Hajnoczi
2019-07-25  3:23 ` [Qemu-devel] [RFC 03/19] fuzz: add fuzz accelerator Oleinik, Alexander
2019-07-26 10:33   ` Paolo Bonzini
2019-07-26 12:35   ` Stefan Hajnoczi
2019-07-25  3:23 ` [Qemu-devel] [RFC 04/19] fuzz: Add qos support to fuzz targets Oleinik, Alexander
2019-07-26 10:39   ` Paolo Bonzini
2019-07-25  3:23 ` [Qemu-devel] [RFC 05/19] fuzz: expose qemu_savevm_state & skip state header Oleinik, Alexander
2019-07-25 13:22   ` Dr. David Alan Gilbert
2019-07-25  3:23 ` [Qemu-devel] [RFC 07/19] fuzz: Modify libqtest to directly invoke qtest.c Oleinik, Alexander
2019-07-25  9:04   ` Thomas Huth
2019-07-25  9:33     ` Paolo Bonzini
2019-07-26 12:49     ` Stefan Hajnoczi
2019-07-26 12:56   ` Stefan Hajnoczi
2019-07-26 21:50     ` Paolo Bonzini
2019-07-25  3:23 ` [Qemu-devel] [RFC 06/19] fuzz: Add ramfile for fast vmstate/vmload Oleinik, Alexander
2019-07-26 12:47   ` Stefan Hajnoczi
2019-07-26 19:36     ` Oleinik, Alexander
2019-07-26 19:54       ` Paolo Bonzini
2019-07-25  3:23 ` [Qemu-devel] [RFC 08/19] fuzz: add shims to intercept libfuzzer init Oleinik, Alexander
2019-07-25  8:21   ` Paolo Bonzini
2019-07-26 12:59     ` Stefan Hajnoczi
2019-07-25  3:23 ` [Qemu-devel] [RFC 09/19] fuzz: use mtree_info to find mapped addresses Oleinik, Alexander
2019-07-26 13:04   ` Stefan Hajnoczi
2019-07-26 21:51     ` Paolo Bonzini
2019-07-25  3:23 ` [Qemu-devel] [RFC 10/19] fuzz: expose real_main (aka regular vl.c:main) Oleinik, Alexander
2019-07-25  9:38   ` Paolo Bonzini
2019-07-25  3:23 ` [Qemu-devel] [RFC 11/19] fuzz: add direct send/receive in qtest client Oleinik, Alexander
2019-07-25  9:10   ` Thomas Huth
2019-07-25  3:23 ` [Qemu-devel] [RFC 12/19] fuzz: hard-code all of the needed files for build Oleinik, Alexander
2019-07-25  3:23 ` [Qemu-devel] [RFC 13/19] fuzz: add ctrl vq support to virtio-net in libqos Oleinik, Alexander
2019-07-25 16:25   ` John Snow
2019-07-25 17:05     ` Oleinik, Alexander
2019-07-26 13:09       ` Stefan Hajnoczi
2019-07-25  3:23 ` [Qemu-devel] [RFC 14/19] fuzz: hard-code a main-loop timeout Oleinik, Alexander
2019-07-25  9:40   ` Paolo Bonzini
2019-07-25  3:23 ` [Qemu-devel] [RFC 15/19] fuzz: add fuzz accelerator type Oleinik, Alexander
2019-07-25  3:23 ` [Qemu-devel] [RFC 16/19] fuzz: add general fuzzer entrypoints Oleinik, Alexander
2019-07-25 17:53   ` Philippe Mathieu-Daudé
2019-07-25  3:23 ` Oleinik, Alexander [this message]
2019-07-25  3:24 ` [Qemu-devel] [RFC 18/19] fuzz: Add virtio-net tx and ctrl fuzz targets Oleinik, Alexander
2019-07-25  3:24 ` [Qemu-devel] [RFC 19/19] fuzz: Add documentation about the fuzzer to docs/ Oleinik, Alexander
2019-07-26 13:19   ` Stefan Hajnoczi
2019-07-25  3:41 ` [Qemu-devel] [RFC 00/19] Add virtual device fuzzing support no-reply
2019-07-26 13:24 ` Stefan Hajnoczi
2019-08-06  9:59 ` jiade zhang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190725032321.12721-18-alxndr@bu.edu \
    --to=alxndr@bu.edu \
    --cc=bsd@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=superirishdonkey@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.