qemu-devel.nongnu.org archive mirror
 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>,
	"stefanha@redhat.com" <stefanha@redhat.com>,
	"Oleinik, Alexander" <alxndr@bu.edu>
Subject: [Qemu-devel] [RFC PATCH v2 15/17] fuzz: Add general qtest fuzz-target
Date: Mon, 5 Aug 2019 07:11:15 +0000	[thread overview]
Message-ID: <20190805071038.32146-16-alxndr@bu.edu> (raw)
In-Reply-To: <20190805071038.32146-1-alxndr@bu.edu>

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



  parent reply	other threads:[~2019-08-05  7:18 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Oleinik, Alexander [this message]
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

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=20190805071038.32146-16-alxndr@bu.edu \
    --to=alxndr@bu.edu \
    --cc=bsd@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).