From: Stefan Hajnoczi <stefanha@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Kevin Wolf" <kwolf@redhat.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Thomas Huth" <thuth@redhat.com>,
"Eduardo Habkost" <ehabkost@redhat.com>,
qemu-block@nongnu.org, "Michael S. Tsirkin" <mst@redhat.com>,
"Laurent Vivier" <lvivier@redhat.com>,
"Max Reitz" <mreitz@redhat.com>,
"Alexander Bulekov" <alxndr@bu.edu>,
"Bandan Das" <bsd@redhat.com>,
"Stefan Hajnoczi" <stefanha@redhat.com>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Fam Zheng" <fam@euphon.net>,
"Darren Kenny" <darren.kenny@oracle.com>,
"Richard Henderson" <rth@twiddle.net>
Subject: [PULL 25/31] fuzz: add support for qos-assisted fuzz targets
Date: Sat, 22 Feb 2020 08:50:24 +0000 [thread overview]
Message-ID: <20200222085030.1760640-26-stefanha@redhat.com> (raw)
In-Reply-To: <20200222085030.1760640-1-stefanha@redhat.com>
From: Alexander Bulekov <alxndr@bu.edu>
Signed-off-by: Alexander Bulekov <alxndr@bu.edu>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Darren Kenny <darren.kenny@oracle.com>
Message-id: 20200220041118.23264-17-alxndr@bu.edu
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
tests/qtest/fuzz/Makefile.include | 2 +
tests/qtest/fuzz/qos_fuzz.c | 234 ++++++++++++++++++++++++++++++
tests/qtest/fuzz/qos_fuzz.h | 33 +++++
3 files changed, 269 insertions(+)
create mode 100644 tests/qtest/fuzz/qos_fuzz.c
create mode 100644 tests/qtest/fuzz/qos_fuzz.h
diff --git a/tests/qtest/fuzz/Makefile.include b/tests/qtest/fuzz/Makefile.include
index a90915d56d..e3bdd33ff4 100644
--- a/tests/qtest/fuzz/Makefile.include
+++ b/tests/qtest/fuzz/Makefile.include
@@ -1,8 +1,10 @@
QEMU_PROG_FUZZ=qemu-fuzz-$(TARGET_NAME)$(EXESUF)
fuzz-obj-y += tests/qtest/libqtest.o
+fuzz-obj-y += $(libqos-obj-y)
fuzz-obj-y += tests/qtest/fuzz/fuzz.o # Fuzzer skeleton
fuzz-obj-y += tests/qtest/fuzz/fork_fuzz.o
+fuzz-obj-y += tests/qtest/fuzz/qos_fuzz.o
FUZZ_CFLAGS += -I$(SRC_PATH)/tests -I$(SRC_PATH)/tests/qtest
diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c
new file mode 100644
index 0000000000..bbb17470ff
--- /dev/null
+++ b/tests/qtest/fuzz/qos_fuzz.c
@@ -0,0 +1,234 @@
+/*
+ * QOS-assisted fuzzing helpers
+ *
+ * Copyright (c) 2018 Emanuele Giuseppe Esposito <e.emanuelegiuseppe@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>
+ */
+
+#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 "tests/qtest/libqtest.h"
+#include "tests/qtest/libqos/malloc.h"
+#include "tests/qtest/libqos/qgraph.h"
+#include "tests/qtest/libqos/qgraph_internal.h"
+#include "tests/qtest/libqos/qos_external.h"
+
+#include "fuzz.h"
+#include "qos_fuzz.h"
+
+#include "qapi/qapi-commands-machine.h"
+#include "qapi/qapi-commands-qom.h"
+#include "qapi/qmp/qlist.h"
+
+
+void *fuzz_qos_obj;
+QGuestAllocator *fuzz_qos_alloc;
+
+static const char *fuzz_target_name;
+static char **fuzz_path_vec;
+
+/*
+ * Replaced the qmp commands with direct qmp_marshal calls.
+ * Probably there is a better way to do this
+ */
+static 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);
+}
+
+static const char *qos_build_main_args(void)
+{
+ char **path = fuzz_path_vec;
+ QOSGraphNode *test_node;
+ GString *cmd_line = g_string_new(path[0]);
+ void *test_arg;
+
+ if (!path) {
+ fprintf(stderr, "QOS Path not found\n");
+ abort();
+ }
+
+ /* 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,
+ TARGET_NAME " -display none -machine accel=qtest -m 64 ");
+ return cmd_line->str;
+}
+
+/*
+ * This function is largely a copy of qos-test.c:walk_path. Since walk_path
+ * is itself a callback, its a little annoying to add another argument/layer of
+ * indirection
+ */
+static 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) == 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);
+
+ fuzz_path_vec = path_vec;
+ } else {
+ g_free(path_vec);
+ }
+
+ g_free(path_str);
+}
+
+static const char *qos_get_cmdline(FuzzTarget *t)
+{
+ /*
+ * Set a global variable that we use to identify the qos_path for our
+ * fuzz_target
+ */
+ fuzz_target_name = t->name;
+ qos_set_machines_devices_available();
+ qos_graph_foreach_test_path(walk_path);
+ return qos_build_main_args();
+}
+
+void fuzz_add_qos_target(
+ FuzzTarget *fuzz_opts,
+ const char *interface,
+ QOSGraphTestOptions *opts
+ )
+{
+ qos_add_test(fuzz_opts->name, interface, NULL, opts);
+ fuzz_opts->get_init_cmdline = qos_get_cmdline;
+ fuzz_add_target(fuzz_opts);
+}
+
+void qos_init_path(QTestState *s)
+{
+ fuzz_qos_obj = qos_allocate_objects(s , &fuzz_qos_alloc);
+}
diff --git a/tests/qtest/fuzz/qos_fuzz.h b/tests/qtest/fuzz/qos_fuzz.h
new file mode 100644
index 0000000000..477f11b02b
--- /dev/null
+++ b/tests/qtest/fuzz/qos_fuzz.h
@@ -0,0 +1,33 @@
+/*
+ * QOS-assisted fuzzing helpers
+ *
+ * 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.
+ */
+
+#ifndef _QOS_FUZZ_H_
+#define _QOS_FUZZ_H_
+
+#include "tests/qtest/fuzz/fuzz.h"
+#include "tests/qtest/libqos/qgraph.h"
+
+int qos_fuzz(const unsigned char *Data, size_t Size);
+void qos_setup(void);
+
+extern void *fuzz_qos_obj;
+extern QGuestAllocator *fuzz_qos_alloc;
+
+void fuzz_add_qos_target(
+ FuzzTarget *fuzz_opts,
+ const char *interface,
+ QOSGraphTestOptions *opts
+ );
+
+void qos_init_path(QTestState *);
+
+#endif
--
2.24.1
next prev parent reply other threads:[~2020-02-22 9:04 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-02-22 8:49 [PULL 00/31] Block patches Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 01/31] virtio: increase virtqueue size for virtio-scsi and virtio-blk Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 02/31] aio-posix: avoid reacquiring rcu_read_lock() when polling Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 03/31] rcu_queue: add QSLIST functions Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 04/31] util/async: make bh_aio_poll() O(1) Stefan Hajnoczi
2020-03-16 16:42 ` Marc-André Lureau
2020-02-22 8:50 ` [PULL 05/31] aio-posix: fix use after leaving scope in aio_poll() Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 06/31] aio-posix: don't pass ns timeout to epoll_wait() Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 07/31] qemu/queue.h: add QLIST_SAFE_REMOVE() Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 08/31] aio-posix: make AioHandler deletion O(1) Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 09/31] aio-posix: make AioHandler dispatch O(1) with epoll Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 10/31] softmmu: move vl.c to softmmu/ Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 11/31] softmmu: split off vl.c:main() into main.c Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 12/31] module: check module wasn't already initialized Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 13/31] fuzz: add FUZZ_TARGET module type Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 14/31] qtest: add qtest_server_send abstraction Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 15/31] libqtest: add a layer of abstraction to send/recv Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 16/31] libqtest: make bufwrite rely on the TransportOps Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 17/31] qtest: add in-process incoming command handler Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 18/31] libqos: rename i2c_send and i2c_recv Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 19/31] libqos: split qos-test and libqos makefile vars Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 20/31] libqos: move useful qos-test funcs to qos_external Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 21/31] fuzz: add fuzzer skeleton Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 22/31] exec: keep ram block across fork when using qtest Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 23/31] main: keep rcu_atfork callback enabled for qtest Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 24/31] fuzz: support for fork-based fuzzing Stefan Hajnoczi
2020-02-22 11:34 ` Eric Blake
2020-02-24 11:35 ` Stefan Hajnoczi
2020-02-27 2:50 ` Alexander Bulekov
2020-02-22 8:50 ` Stefan Hajnoczi [this message]
2020-02-22 8:50 ` [PULL 26/31] fuzz: add target/fuzz makefile rules Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 27/31] fuzz: add configure flag --enable-fuzzing Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 28/31] fuzz: add i440fx fuzz targets Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 29/31] fuzz: add virtio-net fuzz target Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 30/31] fuzz: add virtio-scsi " Stefan Hajnoczi
2020-02-22 8:50 ` [PULL 31/31] fuzz: add documentation to docs/devel/ Stefan Hajnoczi
2020-02-22 9:13 ` [PULL 00/31] Block patches no-reply
2020-02-24 11:33 ` Stefan Hajnoczi
2020-02-24 12:47 ` Peter Maydell
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=20200222085030.1760640-26-stefanha@redhat.com \
--to=stefanha@redhat.com \
--cc=alxndr@bu.edu \
--cc=bsd@redhat.com \
--cc=darren.kenny@oracle.com \
--cc=ehabkost@redhat.com \
--cc=fam@euphon.net \
--cc=kwolf@redhat.com \
--cc=lvivier@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=mreitz@redhat.com \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
--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).