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 16/22] fuzz: add support for qos-assisted fuzz targets
Date: Thu, 20 Feb 2020 10:35:10 +0000 [thread overview]
Message-ID: <20200220103510.cidqn4qqovpaycvl@starbug-mbp> (raw)
In-Reply-To: <20200220041118.23264-17-alxndr@bu.edu>
On Wed, Feb 19, 2020 at 11:11:12PM -0500, Alexander Bulekov wrote:
>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 | 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.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 [this message]
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
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=20200220103510.cidqn4qqovpaycvl@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).