From: Darren Kenny <darren.kenny@oracle.com>
To: Alexander Bulekov <alxndr@bu.edu>
Cc: Laurent Vivier <lvivier@redhat.com>,
Thomas Huth <thuth@redhat.com>,
qemu-devel@nongnu.org, bsd@redhat.com, stefanha@redhat.com,
pbonzini@redhat.com
Subject: Re: [PATCH v10 21/22] fuzz: add virtio-scsi fuzz target
Date: Thu, 20 Feb 2020 10:38:54 +0000 [thread overview]
Message-ID: <20200220103854.rfhudwoovajac5w5@starbug-mbp> (raw)
In-Reply-To: <20200220041118.23264-22-alxndr@bu.edu>
On Wed, Feb 19, 2020 at 11:11:17PM -0500, Alexander Bulekov wrote:
>The virtio-scsi fuzz target sets up and fuzzes the available virtio-scsi
>queues. After an element is placed on a queue, the fuzzer can select
>whether to perform a kick, or continue adding elements.
>
>Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
>---
> tests/qtest/fuzz/Makefile.include | 1 +
> tests/qtest/fuzz/virtio_scsi_fuzz.c | 213 ++++++++++++++++++++++++++++
> 2 files changed, 214 insertions(+)
> create mode 100644 tests/qtest/fuzz/virtio_scsi_fuzz.c
>
>diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
>index 77385777ef..cde3e9636c 100644
>--- a/tests/qtest/fuzz/Makefile.include
>+++ b/tests/qtest/fuzz/Makefile.include
>@@ -9,6 +9,7 @@ fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
> # Targets
> fuzz-obj-y += tests/qtest/fuzz/i440fx_fuzz.o
> fuzz-obj-y += tests/qtest/fuzz/virtio_net_fuzz.o
>+fuzz-obj-y += tests/qtest/fuzz/virtio_scsi_fuzz.o
>
> FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
>
>diff --git a/tests/qtest/fuzz/virtio_scsi_fuzz.c b/tests/qtest/fuzz/virtio_scsi_fuzz.c
>new file mode 100644
>index 0000000000..3b95247f12
>--- /dev/null
>+++ b/tests/qtest/fuzz/virtio_scsi_fuzz.c
>@@ -0,0 +1,213 @@
>+/*
>+ * virtio-serial Fuzzing Target
>+ *
>+ * Copyright Red Hat Inc., 2019
>+ *
>+ * Authors:
>+ * Alexander Bulekov <alxndr@bu.edu>
>+ *
>+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
>+ * See the COPYING file in the top-level directory.
>+ */
>+
>+#include "qemu/osdep.h"
>+
>+#include "tests/qtest/libqtest.h"
>+#include "libqos/virtio-scsi.h"
>+#include "libqos/virtio.h"
>+#include "libqos/virtio-pci.h"
>+#include "standard-headers/linux/virtio_ids.h"
>+#include "standard-headers/linux/virtio_pci.h"
>+#include "standard-headers/linux/virtio_scsi.h"
>+#include "fuzz.h"
>+#include "fork_fuzz.h"
>+#include "qos_fuzz.h"
>+
>+#define PCI_SLOT 0x02
>+#define PCI_FN 0x00
>+#define QVIRTIO_SCSI_TIMEOUT_US (1 * 1000 * 1000)
>+
>+#define MAX_NUM_QUEUES 64
>+
>+/* Based on tests/virtio-scsi-test.c */
>+typedef struct {
>+ int num_queues;
>+ QVirtQueue *vq[MAX_NUM_QUEUES + 2];
>+} QVirtioSCSIQueues;
>+
>+static QVirtioSCSIQueues *qvirtio_scsi_init(QVirtioDevice *dev, uint64_t mask)
>+{
>+ QVirtioSCSIQueues *vs;
>+ uint64_t feat;
>+ int i;
>+
>+ vs = g_new0(QVirtioSCSIQueues, 1);
>+
>+ feat = qvirtio_get_features(dev);
>+ if (mask) {
>+ feat &= ~QVIRTIO_F_BAD_FEATURE | mask;
>+ } else {
>+ feat &= ~(QVIRTIO_F_BAD_FEATURE | (1ull << VIRTIO_RING_F_EVENT_IDX));
>+ }
>+ qvirtio_set_features(dev, feat);
>+
>+ vs->num_queues = qvirtio_config_readl(dev, 0);
>+
>+ for (i = 0; i < vs->num_queues + 2; i++) {
>+ vs->vq[i] = qvirtqueue_setup(dev, fuzz_qos_alloc, i);
>+ }
>+
>+ qvirtio_set_driver_ok(dev);
>+
>+ return vs;
>+}
>+
>+static void virtio_scsi_fuzz(QTestState *s, QVirtioSCSIQueues* queues,
>+ const unsigned char *Data, size_t Size)
>+{
>+ /*
>+ * Data is a sequence of random bytes. We split them up into "actions",
>+ * followed by data:
>+ * [vqa][dddddddd][vqa][dddd][vqa][dddddddddddd] ...
>+ * The length of the data is specified by the preceding vqa.length
>+ */
>+ typedef struct vq_action {
>+ uint8_t queue;
>+ uint8_t length;
>+ uint8_t write;
>+ uint8_t next;
>+ uint8_t kick;
>+ } vq_action;
>+
>+ /* Keep track of the free head for each queue we interact with */
>+ bool vq_touched[MAX_NUM_QUEUES + 2] = {0};
>+ uint32_t free_head[MAX_NUM_QUEUES + 2];
>+
>+ QGuestAllocator *t_alloc = fuzz_qos_alloc;
>+
>+ QVirtioSCSI *scsi = fuzz_qos_obj;
>+ QVirtioDevice *dev = scsi->vdev;
>+ QVirtQueue *q;
>+ vq_action vqa;
>+ while (Size >= sizeof(vqa)) {
>+ /* Copy the action, so we can normalize length, queue and flags */
>+ memcpy(&vqa, Data, sizeof(vqa));
>+
>+ Data += sizeof(vqa);
>+ Size -= sizeof(vqa);
>+
>+ vqa.queue = vqa.queue % queues->num_queues;
>+ /* Cap length at the number of remaining bytes in data */
>+ vqa.length = vqa.length >= Size ? Size : vqa.length;
>+ vqa.write = vqa.write & 1;
>+ vqa.next = vqa.next & 1;
>+ vqa.kick = vqa.kick & 1;
>+
>+
>+ q = queues->vq[vqa.queue];
>+
>+ /* Copy the data into ram, and place it on the virtqueue */
>+ uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
>+ qtest_memwrite(s, req_addr, Data, vqa.length);
>+ if (vq_touched[vqa.queue] == 0) {
>+ vq_touched[vqa.queue] = 1;
>+ free_head[vqa.queue] = qvirtqueue_add(s, q, req_addr, vqa.length,
>+ vqa.write, vqa.next);
>+ } else {
>+ qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
>+ }
>+
>+ if (vqa.kick) {
>+ qvirtqueue_kick(s, dev, q, free_head[vqa.queue]);
>+ free_head[vqa.queue] = 0;
>+ }
>+ Data += vqa.length;
>+ Size -= vqa.length;
>+ }
>+ /* In the end, kick each queue we interacted with */
>+ for (int i = 0; i < MAX_NUM_QUEUES + 2; i++) {
>+ if (vq_touched[i]) {
>+ qvirtqueue_kick(s, dev, queues->vq[i], free_head[i]);
>+ }
>+ }
>+}
>+
>+static void virtio_scsi_fork_fuzz(QTestState *s,
>+ const unsigned char *Data, size_t Size)
>+{
>+ QVirtioSCSI *scsi = fuzz_qos_obj;
>+ static QVirtioSCSIQueues *queues;
>+ if (!queues) {
>+ queues = qvirtio_scsi_init(scsi->vdev, 0);
>+ }
>+ if (fork() == 0) {
>+ virtio_scsi_fuzz(s, queues, Data, Size);
>+ flush_events(s);
>+ _Exit(0);
>+ } else {
>+ wait(NULL);
>+ }
>+}
>+
>+static void virtio_scsi_with_flag_fuzz(QTestState *s,
>+ const unsigned char *Data, size_t Size)
>+{
>+ QVirtioSCSI *scsi = fuzz_qos_obj;
>+ static QVirtioSCSIQueues *queues;
>+
>+ if (fork() == 0) {
>+ if (Size >= sizeof(uint64_t)) {
>+ queues = qvirtio_scsi_init(scsi->vdev, *(uint64_t *)Data);
>+ virtio_scsi_fuzz(s, queues,
>+ Data + sizeof(uint64_t), Size - sizeof(uint64_t));
>+ flush_events(s);
>+ }
>+ _Exit(0);
>+ } else {
>+ wait(NULL);
>+ }
>+}
>+
>+static void virtio_scsi_pre_fuzz(QTestState *s)
>+{
>+ qos_init_path(s);
>+ counter_shm_init();
>+}
>+
>+static void *virtio_scsi_test_setup(GString *cmd_line, void *arg)
>+{
>+ g_string_append(cmd_line,
>+ " -drive file=blkdebug::null-co://,"
>+ "file.image.read-zeroes=on,"
>+ "if=none,id=dr1,format=raw,file.align=4k "
>+ "-device scsi-hd,drive=dr1,lun=0,scsi-id=1");
>+ return arg;
>+}
>+
>+
>+static void register_virtio_scsi_fuzz_targets(void)
>+{
>+ fuzz_add_qos_target(&(FuzzTarget){
>+ .name = "virtio-scsi-fuzz",
>+ .description = "Fuzz the virtio-scsi virtual queues, forking"
>+ "for each fuzz run",
>+ .pre_vm_init = &counter_shm_init,
>+ .pre_fuzz = &virtio_scsi_pre_fuzz,
>+ .fuzz = virtio_scsi_fork_fuzz,},
>+ "virtio-scsi",
>+ &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
>+ );
>+
>+ fuzz_add_qos_target(&(FuzzTarget){
>+ .name = "virtio-scsi-flags-fuzz",
>+ .description = "Fuzz the virtio-scsi virtual queues, forking"
>+ "for each fuzz run (also fuzzes the virtio flags)",
>+ .pre_vm_init = &counter_shm_init,
>+ .pre_fuzz = &virtio_scsi_pre_fuzz,
>+ .fuzz = virtio_scsi_with_flag_fuzz,},
>+ "virtio-scsi",
>+ &(QOSGraphTestOptions){.before = virtio_scsi_test_setup}
>+ );
>+}
>+
>+fuzz_target_init(register_virtio_scsi_fuzz_targets);
>--
>2.25.0
>
next prev parent reply other threads:[~2020-02-20 10:40 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-20 4:10 [PATCH v10 00/22] Add virtual device fuzzing support Alexander Bulekov
2020-02-20 4:10 ` [PATCH v10 01/22] softmmu: move vl.c to softmmu/ Alexander Bulekov
2020-02-20 10:33 ` Darren Kenny
2020-02-21 13:56 ` Stefan Hajnoczi
2020-02-20 4:10 ` [PATCH v10 02/22] softmmu: split off vl.c:main() into main.c Alexander Bulekov
2020-02-20 4:10 ` [PATCH v10 03/22] module: check module wasn't already initialized Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 04/22] fuzz: add FUZZ_TARGET module type Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 05/22] qtest: add qtest_server_send abstraction Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 06/22] libqtest: add a layer of abstraction to send/recv Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 07/22] libqtest: make bufwrite rely on the TransportOps Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 08/22] qtest: add in-process incoming command handler Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 09/22] libqos: rename i2c_send and i2c_recv Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 10/22] libqos: split qos-test and libqos makefile vars Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 11/22] libqos: move useful qos-test funcs to qos_external Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 12/22] fuzz: add fuzzer skeleton Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 13/22] exec: keep ram block across fork when using qtest Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 14/22] main: keep rcu_atfork callback enabled for qtest Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 15/22] fuzz: support for fork-based fuzzing Alexander Bulekov
2020-02-20 10:34 ` Darren Kenny
2020-02-20 4:11 ` [PATCH v10 16/22] fuzz: add support for qos-assisted fuzz targets Alexander Bulekov
2020-02-20 10:35 ` Darren Kenny
2020-02-20 4:11 ` [PATCH v10 17/22] fuzz: add target/fuzz makefile rules Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 18/22] fuzz: add configure flag --enable-fuzzing Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 19/22] fuzz: add i440fx fuzz targets Alexander Bulekov
2020-02-20 4:11 ` [PATCH v10 20/22] fuzz: add virtio-net fuzz target Alexander Bulekov
2020-02-20 10:35 ` Darren Kenny
2020-02-20 4:11 ` [PATCH v10 21/22] fuzz: add virtio-scsi " Alexander Bulekov
2020-02-20 10:38 ` Darren Kenny [this message]
2020-02-21 13:57 ` Stefan Hajnoczi
2020-02-20 4:11 ` [PATCH v10 22/22] fuzz: add documentation to docs/devel/ Alexander Bulekov
2020-02-21 15:17 ` [PATCH v10 00/22] Add virtual device fuzzing support Stefan Hajnoczi
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=20200220103854.rfhudwoovajac5w5@starbug-mbp \
--to=darren.kenny@oracle.com \
--cc=alxndr@bu.edu \
--cc=bsd@redhat.com \
--cc=lvivier@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=thuth@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).