summaryrefslogtreecommitdiff
path: root/src/fuzz
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-05-05 19:04:01 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2022-05-08 17:58:00 +0200
commit1409ce6ed2e7e741e61bc326dbed856cb4eaf97c (patch)
tree2d4ef7737dd60d6f7422886e7a262662843f5cea /src/fuzz
parenta847b539de828bf7e877cf0f8a014a8360d32a79 (diff)
downloadsystemd-1409ce6ed2e7e741e61bc326dbed856cb4eaf97c.tar.gz
Add fuzzer for the bootspec parser
Diffstat (limited to 'src/fuzz')
-rw-r--r--src/fuzz/fuzz-bootspec-gen.py18
-rw-r--r--src/fuzz/fuzz-bootspec.c108
-rw-r--r--src/fuzz/meson.build2
3 files changed, 128 insertions, 0 deletions
diff --git a/src/fuzz/fuzz-bootspec-gen.py b/src/fuzz/fuzz-bootspec-gen.py
new file mode 100644
index 0000000000..aaacbbe7f5
--- /dev/null
+++ b/src/fuzz/fuzz-bootspec-gen.py
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+
+"""Generate sample input for fuzz-bootspec"""
+
+import json
+import os
+import sys
+
+config = open(sys.argv[1]).read()
+entries = [(os.path.basename(name), open(name).read())
+ for name in sys.argv[2:]]
+
+data = {
+ 'config': config,
+ 'entries': entries,
+}
+
+print(json.dumps(data, indent=4))
diff --git a/src/fuzz/fuzz-bootspec.c b/src/fuzz/fuzz-bootspec.c
new file mode 100644
index 0000000000..9907457450
--- /dev/null
+++ b/src/fuzz/fuzz-bootspec.c
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+#include <string.h>
+
+#include "bootspec.h"
+#include "env-util.h"
+#include "escape.h"
+#include "fuzz.h"
+#include "fd-util.h"
+#include "json.h"
+
+static int json_dispatch_config(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+ BootConfig *config = ASSERT_PTR(userdata);
+
+ const char *s = json_variant_string(variant);
+ if (!s)
+ return -EINVAL;
+
+ _cleanup_fclose_ FILE *f = NULL;
+ assert_se(f = data_to_file((const uint8_t*) s, strlen(s)));
+
+ (void) boot_loader_read_conf(config, f, "memstream");
+ return 0;
+}
+
+static int json_dispatch_entries(const char *name, JsonVariant *variant, JsonDispatchFlags flags, void *userdata) {
+ BootConfig *config = ASSERT_PTR(userdata);
+ JsonVariant *entry;
+
+ JSON_VARIANT_ARRAY_FOREACH(entry, variant) {
+ if (!json_variant_is_array(entry) ||
+ json_variant_elements(entry) < 1)
+ return -EINVAL;
+
+ JsonVariant *v;
+ const char *id = NULL, *raw = NULL;
+ _cleanup_free_ char *data = NULL;
+ ssize_t len = -ENODATA;
+
+ v = json_variant_by_index(entry, 0);
+ if (v)
+ id = json_variant_string(v);
+ if (!id)
+ continue;
+
+ v = json_variant_by_index(entry, 1);
+ if (v)
+ raw = json_variant_string(v);
+ if (raw)
+ len = cunescape(raw, UNESCAPE_RELAX | UNESCAPE_ACCEPT_NUL, &data);
+ if (len >= 0) {
+ _cleanup_fclose_ FILE *f = NULL;
+ assert_se(f = data_to_file((const uint8_t*) data, len));
+
+ assert_se(boot_config_load_type1(config, f, "/", "/entries", id) != -ENOMEM);
+ }
+ }
+
+ return 0;
+}
+
+static const JsonDispatch data_dispatch[] = {
+ { "config", JSON_VARIANT_STRING, json_dispatch_config, 0, 0 },
+ { "entries", JSON_VARIANT_ARRAY, json_dispatch_entries, 0, 0 },
+ {}
+};
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_free_ const char *datadup = NULL;
+ _cleanup_(boot_config_free) BootConfig config = BOOT_CONFIG_NULL;
+ int r;
+
+ /* Disable most logging if not running standalone */
+ if (!getenv("SYSTEMD_LOG_LEVEL"))
+ log_set_max_level(LOG_CRIT);
+
+ assert_se(datadup = memdup_suffix0(data, size));
+
+ _cleanup_(json_variant_unrefp) JsonVariant *v = NULL;
+ r = json_parse(datadup, 0, &v, NULL, NULL);
+ if (r < 0)
+ return 0;
+
+ r = json_dispatch(v, data_dispatch, NULL, 0, &config);
+ if (r < 0)
+ return 0;
+
+ assert_se(boot_config_finalize(&config) >= 0);
+
+ (void) boot_config_select_special_entries(&config);
+
+ _cleanup_close_ int orig_stdout_fd = -1;
+ if (getenv_bool("SYSTEMD_FUZZ_OUTPUT") <= 0) {
+ orig_stdout_fd = fcntl(fileno(stdout), F_DUPFD_CLOEXEC, 3);
+ if (orig_stdout_fd < 0)
+ log_warning_errno(orig_stdout_fd, "Failed to duplicate fd 1: %m");
+ else
+ assert_se(freopen("/dev/null", "w", stdout));
+ }
+
+ (void) show_boot_entries(&config, JSON_FORMAT_OFF);
+ (void) show_boot_entries(&config, JSON_FORMAT_PRETTY);
+
+ if (orig_stdout_fd >= 0)
+ assert_se(freopen(FORMAT_PROC_FD_PATH(orig_stdout_fd), "w", stdout));
+
+ return 0;
+}
diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build
index b92fb95e8a..6f36536f1b 100644
--- a/src/fuzz/meson.build
+++ b/src/fuzz/meson.build
@@ -1,6 +1,8 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
fuzzers += [
+ [files('fuzz-bootspec.c')],
+
[files('fuzz-bus-label.c')],
[files('fuzz-calendarspec.c')],