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 20/22] fuzz: add virtio-net fuzz target
Date: Thu, 20 Feb 2020 10:35:46 +0000 [thread overview]
Message-ID: <20200220103546.fpw6tu22kjl3y4bc@starbug-mbp> (raw)
In-Reply-To: <20200220041118.23264-21-alxndr@bu.edu>
On Wed, Feb 19, 2020 at 11:11:16PM -0500, Alexander Bulekov wrote:
>The virtio-net fuzz target feeds inputs to all three virtio-net
>virtqueues, and uses forking to avoid leaking state between fuzz runs.
>
>Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
>Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
>---
> tests/qtest/fuzz/Makefile.include | 1 +
> tests/qtest/fuzz/virtio_net_fuzz.c | 198 +++++++++++++++++++++++++++++
> 2 files changed, 199 insertions(+)
> create mode 100644 tests/qtest/fuzz/virtio_net_fuzz.c
>
>diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
>index 38b8cdd9f1..77385777ef 100644
>--- a/tests/qtest/fuzz/Makefile.include
>+++ b/tests/qtest/fuzz/Makefile.include
>@@ -8,6 +8,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_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
>
>diff --git a/tests/qtest/fuzz/virtio_net_fuzz.c b/tests/qtest/fuzz/virtio_net_fuzz.c
>new file mode 100644
>index 0000000000..d08a47e278
>--- /dev/null
>+++ b/tests/qtest/fuzz/virtio_net_fuzz.c
>@@ -0,0 +1,198 @@
>+/*
>+ * virtio-net 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 "standard-headers/linux/virtio_config.h"
>+#include "tests/qtest/libqtest.h"
>+#include "tests/qtest/libqos/virtio-net.h"
>+#include "fuzz.h"
>+#include "fork_fuzz.h"
>+#include "qos_fuzz.h"
>+
>+
>+#define QVIRTIO_NET_TIMEOUT_US (30 * 1000 * 1000)
>+#define QVIRTIO_RX_VQ 0
>+#define QVIRTIO_TX_VQ 1
>+#define QVIRTIO_CTRL_VQ 2
>+
>+static int sockfds[2];
>+static bool sockfds_initialized;
>+
>+static void virtio_net_fuzz_multi(QTestState *s,
>+ const unsigned char *Data, size_t Size, bool check_used)
>+{
>+ typedef struct vq_action {
>+ uint8_t queue;
>+ uint8_t length;
>+ uint8_t write;
>+ uint8_t next;
>+ uint8_t rx;
>+ } vq_action;
>+
>+ uint32_t free_head = 0;
>+
>+ QGuestAllocator *t_alloc = fuzz_qos_alloc;
>+
>+ QVirtioNet *net_if = fuzz_qos_obj;
>+ QVirtioDevice *dev = net_if->vdev;
>+ QVirtQueue *q;
>+ vq_action vqa;
>+ while (Size >= sizeof(vqa)) {
>+ memcpy(&vqa, Data, sizeof(vqa));
>+ Data += sizeof(vqa);
>+ Size -= sizeof(vqa);
>+
>+ q = net_if->queues[vqa.queue % 3];
>+
>+ vqa.length = vqa.length >= Size ? Size : vqa.length;
>+
>+ /*
>+ * Only attempt to write incoming packets, when using the socket
>+ * backend. Otherwise, always place the input on a virtqueue.
>+ */
>+ if (vqa.rx && sockfds_initialized) {
>+ write(sockfds[0], Data, vqa.length);
>+ } else {
>+ vqa.rx = 0;
>+ uint64_t req_addr = guest_alloc(t_alloc, vqa.length);
>+ /*
>+ * If checking used ring, ensure that the fuzzer doesn't trigger
>+ * trivial asserion failure on zero-zied buffer
>+ */
>+ qtest_memwrite(s, req_addr, Data, vqa.length);
>+
>+
>+ free_head = qvirtqueue_add(s, q, req_addr, vqa.length,
>+ vqa.write, vqa.next);
>+ qvirtqueue_add(s, q, req_addr, vqa.length, vqa.write , vqa.next);
>+ qvirtqueue_kick(s, dev, q, free_head);
>+ }
>+
>+ /* Run the main loop */
>+ qtest_clock_step(s, 100);
>+ flush_events(s);
>+
>+ /* Wait on used descriptors */
>+ if (check_used && !vqa.rx) {
>+ gint64 start_time = g_get_monotonic_time();
>+ /*
>+ * normally, we could just use qvirtio_wait_used_elem, but since we
>+ * must manually run the main-loop for all the bhs to run, we use
>+ * this hack with flush_events(), to run the main_loop
>+ */
>+ while (!vqa.rx && q != net_if->queues[QVIRTIO_RX_VQ]) {
>+ uint32_t got_desc_idx;
>+ /* Input led to a virtio_error */
>+ if (dev->bus->get_status(dev) & VIRTIO_CONFIG_S_NEEDS_RESET) {
>+ break;
>+ }
>+ if (dev->bus->get_queue_isr_status(dev, q) &&
>+ qvirtqueue_get_buf(s, q, &got_desc_idx, NULL)) {
>+ g_assert_cmpint(got_desc_idx, ==, free_head);
>+ break;
>+ }
>+ g_assert(g_get_monotonic_time() - start_time
>+ <= QVIRTIO_NET_TIMEOUT_US);
>+
>+ /* Run the main loop */
>+ qtest_clock_step(s, 100);
>+ flush_events(s);
>+ }
>+ }
>+ Data += vqa.length;
>+ Size -= vqa.length;
>+ }
>+}
>+
>+static void virtio_net_fork_fuzz(QTestState *s,
>+ const unsigned char *Data, size_t Size)
>+{
>+ if (fork() == 0) {
>+ virtio_net_fuzz_multi(s, Data, Size, false);
>+ flush_events(s);
>+ _Exit(0);
>+ } else {
>+ wait(NULL);
>+ }
>+}
>+
>+static void virtio_net_fork_fuzz_check_used(QTestState *s,
>+ const unsigned char *Data, size_t Size)
>+{
>+ if (fork() == 0) {
>+ virtio_net_fuzz_multi(s, Data, Size, true);
>+ flush_events(s);
>+ _Exit(0);
>+ } else {
>+ wait(NULL);
>+ }
>+}
>+
>+static void virtio_net_pre_fuzz(QTestState *s)
>+{
>+ qos_init_path(s);
>+ counter_shm_init();
>+}
>+
>+static void *virtio_net_test_setup_socket(GString *cmd_line, void *arg)
>+{
>+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, sockfds);
>+ g_assert_cmpint(ret, !=, -1);
>+ fcntl(sockfds[0], F_SETFL, O_NONBLOCK);
>+ sockfds_initialized = true;
>+ g_string_append_printf(cmd_line, " -netdev socket,fd=%d,id=hs0 ",
>+ sockfds[1]);
>+ return arg;
>+}
>+
>+static void *virtio_net_test_setup_user(GString *cmd_line, void *arg)
>+{
>+ g_string_append_printf(cmd_line, " -netdev user,id=hs0 ");
>+ return arg;
>+}
>+
>+static void register_virtio_net_fuzz_targets(void)
>+{
>+ fuzz_add_qos_target(&(FuzzTarget){
>+ .name = "virtio-net-socket",
>+ .description = "Fuzz the virtio-net virtual queues. Fuzz incoming "
>+ "traffic using the socket backend",
>+ .pre_fuzz = &virtio_net_pre_fuzz,
>+ .fuzz = virtio_net_fork_fuzz,},
>+ "virtio-net",
>+ &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
>+ );
>+
>+ fuzz_add_qos_target(&(FuzzTarget){
>+ .name = "virtio-net-socket-check-used",
>+ .description = "Fuzz the virtio-net virtual queues. Wait for the "
>+ "descriptors to be used. Timeout may indicate improperly handled "
>+ "input",
>+ .pre_fuzz = &virtio_net_pre_fuzz,
>+ .fuzz = virtio_net_fork_fuzz_check_used,},
>+ "virtio-net",
>+ &(QOSGraphTestOptions){.before = virtio_net_test_setup_socket}
>+ );
>+ fuzz_add_qos_target(&(FuzzTarget){
>+ .name = "virtio-net-slirp",
>+ .description = "Fuzz the virtio-net virtual queues with the slirp "
>+ " backend. Warning: May result in network traffic emitted from the "
>+ " process. Run in an isolated network environment.",
>+ .pre_fuzz = &virtio_net_pre_fuzz,
>+ .fuzz = virtio_net_fork_fuzz,},
>+ "virtio-net",
>+ &(QOSGraphTestOptions){.before = virtio_net_test_setup_user}
>+ );
>+}
>+
>+fuzz_target_init(register_virtio_net_fuzz_targets);
>--
>2.25.0
>
next prev parent reply other threads:[~2020-02-20 10:36 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 [this message]
2020-02-20 4:11 ` [PATCH v10 21/22] fuzz: add virtio-scsi " Alexander Bulekov
2020-02-20 10:38 ` Darren Kenny
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=20200220103546.fpw6tu22kjl3y4bc@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 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.