summaryrefslogtreecommitdiff
path: root/test/fuzz
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2022-07-11 10:18:13 -0400
committerTom Rini <[email protected]>2022-07-11 14:58:57 -0400
commit36b661dc919da318c163a45f4a220d2e3d9db608 (patch)
tree268703050f58280feb3287d48eb0cedc974730e1 /test/fuzz
parente092e3250270a1016c877da7bdd9384f14b1321e (diff)
parent05a4859637567b13219efd6f1707fb236648b1b7 (diff)
Merge branch 'next'
Diffstat (limited to 'test/fuzz')
-rw-r--r--test/fuzz/Makefile8
-rw-r--r--test/fuzz/cmd_fuzz.c82
-rw-r--r--test/fuzz/virtio.c72
3 files changed, 162 insertions, 0 deletions
diff --git a/test/fuzz/Makefile b/test/fuzz/Makefile
new file mode 100644
index 00000000000..663b79ce80b
--- /dev/null
+++ b/test/fuzz/Makefile
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0+
+#
+# Copyright (c) 2022 Google, Inc.
+# Written by Andrew Scull <[email protected]>
+#
+
+obj-$(CONFIG_$(SPL_)CMDLINE) += cmd_fuzz.o
+obj-$(CONFIG_VIRTIO_SANDBOX) += virtio.o
diff --git a/test/fuzz/cmd_fuzz.c b/test/fuzz/cmd_fuzz.c
new file mode 100644
index 00000000000..0cc01dc199c
--- /dev/null
+++ b/test/fuzz/cmd_fuzz.c
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <[email protected]>
+ */
+
+#include <command.h>
+#include <common.h>
+#include <dm.h>
+#include <fuzzing_engine.h>
+#include <test/fuzz.h>
+
+static struct fuzz_test *find_fuzz_test(const char *name)
+{
+ struct fuzz_test *fuzzer = FUZZ_TEST_START();
+ size_t count = FUZZ_TEST_COUNT();
+ size_t i;
+
+ for (i = 0; i < count; ++i) {
+ if (strcmp(name, fuzzer->name) == 0)
+ return fuzzer;
+ ++fuzzer;
+ }
+
+ return NULL;
+}
+
+static struct udevice *find_fuzzing_engine(void)
+{
+ struct udevice *dev;
+
+ if (uclass_first_device(UCLASS_FUZZING_ENGINE, &dev))
+ return NULL;
+
+ return dev;
+}
+
+static int do_fuzz(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+ struct fuzz_test *fuzzer;
+ struct udevice *dev;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ fuzzer = find_fuzz_test(argv[1]);
+ if (!fuzzer) {
+ printf("Could not find fuzzer: %s\n", argv[1]);
+ return 1;
+ }
+
+ dev = find_fuzzing_engine();
+ if (!dev) {
+ puts("No fuzzing engine available\n");
+ return 1;
+ }
+
+ while (1) {
+ const uint8_t *data;
+ size_t size;
+
+ if (dm_fuzzing_engine_get_input(dev, &data, &size)) {
+ puts("Fuzzing engine failed\n");
+ return 1;
+ }
+
+ fuzzer->func(data, size);
+ }
+
+ return 1;
+}
+
+#ifdef CONFIG_SYS_LONGHELP
+static char fuzz_help_text[] =
+ "[fuzz-test-name] - execute the named fuzz test\n"
+ ;
+#endif /* CONFIG_SYS_LONGHELP */
+
+U_BOOT_CMD(
+ fuzz, CONFIG_SYS_MAXARGS, 1, do_fuzz,
+ "fuzz tests", fuzz_help_text
+);
diff --git a/test/fuzz/virtio.c b/test/fuzz/virtio.c
new file mode 100644
index 00000000000..e5363d5638e
--- /dev/null
+++ b/test/fuzz/virtio.c
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2022 Google, Inc.
+ * Written by Andrew Scull <[email protected]>
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <virtio.h>
+#include <virtio_ring.h>
+#include <test/fuzz.h>
+
+static int fuzz_vring(const uint8_t *data, size_t size)
+{
+ struct udevice *bus, *dev;
+ struct virtio_dev_priv *uc_priv;
+ struct virtqueue *vq;
+ struct virtio_sg sg[2];
+ struct virtio_sg *sgs[2];
+ unsigned int len;
+ u8 buffer[2][32];
+
+ /* hackily hardcode vring sizes */
+ size_t num = 4;
+ size_t desc_size = (sizeof(struct vring_desc) * num);
+ size_t avail_size = (3 + num) * sizeof(u16);
+ size_t used_size = (3 * sizeof(u16)) + (sizeof(struct vring_used_elem) * num);
+
+ if (size < (desc_size + avail_size + used_size))
+ return 0;
+
+ /* check probe success */
+ if (uclass_first_device(UCLASS_VIRTIO, &bus) || !bus)
+ panic("Could not find virtio bus\n");
+
+ /* check the child virtio-rng device is bound */
+ if (device_find_first_child(bus, &dev) || !dev)
+ panic("Could not find virtio device\n");
+
+ /*
+ * fake the virtio device probe by filling in uc_priv->vdev
+ * which is used by virtio_find_vqs/virtio_del_vqs.
+ */
+ uc_priv = dev_get_uclass_priv(bus);
+ uc_priv->vdev = dev;
+
+ /* prepare the scatter-gather buffer */
+ sg[0].addr = buffer[0];
+ sg[0].length = sizeof(buffer[0]);
+ sg[1].addr = buffer[1];
+ sg[1].length = sizeof(buffer[1]);
+ sgs[0] = &sg[0];
+ sgs[1] = &sg[1];
+
+ if (virtio_find_vqs(dev, 1, &vq))
+ panic("Could not find vqs\n");
+ if (virtqueue_add(vq, sgs, 0, 1))
+ panic("Could not add to virtqueue\n");
+ /* Simulate device writing to vring */
+ memcpy(vq->vring.desc, data, desc_size);
+ memcpy(vq->vring.avail, data + desc_size, avail_size);
+ memcpy(vq->vring.used, data + desc_size + avail_size, used_size);
+ /* Make sure there is a response */
+ if (vq->vring.used->idx == 0)
+ vq->vring.used->idx = 1;
+ virtqueue_get_buf(vq, &len);
+ if (virtio_del_vqs(dev))
+ panic("Could not delete vqs\n");
+
+ return 0;
+}
+FUZZ_TEST(fuzz_vring, 0);