summaryrefslogtreecommitdiff
path: root/src/fuzz
diff options
context:
space:
mode:
authorEvgeny Vereshchagin <evvers@ya.ru>2018-11-26 12:14:30 +0300
committerYu Watanabe <watanabe.yu+github@gmail.com>2018-11-26 18:14:30 +0900
commit2e646cbed864e07feb06297c1de09251f18f28d2 (patch)
tree841924dee92743a24cf92e2cec8aee963c4945ec /src/fuzz
parent87da558f2b65a2afefd6fae9fe211bcc4b9d0ee9 (diff)
downloadsystemd-2e646cbed864e07feb06297c1de09251f18f28d2.tar.gz
tests: add a fuzzer for the udev rules parser (#10929)
Diffstat (limited to 'src/fuzz')
-rw-r--r--src/fuzz/fuzz-main.c3
-rw-r--r--src/fuzz/fuzz-udev-rules.c95
-rw-r--r--src/fuzz/meson.build8
3 files changed, 105 insertions, 1 deletions
diff --git a/src/fuzz/fuzz-main.c b/src/fuzz/fuzz-main.c
index cc9252377a..d5c9984989 100644
--- a/src/fuzz/fuzz-main.c
+++ b/src/fuzz/fuzz-main.c
@@ -36,7 +36,8 @@ int main(int argc, char **argv) {
printf("%s... ", name);
fflush(stdout);
for (int j = 0; j < MIN_NUMBER_OF_RUNS; j++)
- (void) LLVMFuzzerTestOneInput((uint8_t*)buf, size);
+ if (LLVMFuzzerTestOneInput((uint8_t*)buf, size) == EXIT_TEST_SKIP)
+ return EXIT_TEST_SKIP;
printf("ok\n");
}
diff --git a/src/fuzz/fuzz-udev-rules.c b/src/fuzz/fuzz-udev-rules.c
new file mode 100644
index 0000000000..36c39e1dba
--- /dev/null
+++ b/src/fuzz/fuzz-udev-rules.c
@@ -0,0 +1,95 @@
+/* SPDX-License-Identifier: LGPL-2.1+ */
+
+#include <errno.h>
+#include <sched.h>
+#include <sys/mount.h>
+#include <unistd.h>
+
+#include "fd-util.h"
+#include "fs-util.h"
+#include "fuzz.h"
+#include "log.h"
+#include "mkdir.h"
+#include "missing.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "tests.h"
+#include "udev.h"
+
+static const struct fakefs {
+ const char *target;
+ bool ignore_mount_error;
+} fakefss[] = {
+ { "/sys", false },
+ { "/dev", false },
+ { "/run", false },
+ { "/etc", false },
+ { UDEVLIBEXECDIR "/rules.d", true },
+};
+
+static int setup_mount_namespace(void) {
+ static thread_local bool is_namespaced = false;
+
+ if (is_namespaced)
+ return 1;
+
+ if (unshare(CLONE_NEWNS) < 0)
+ return log_error_errno(errno, "Failed to call unshare(): %m");
+
+ if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
+ return log_error_errno(errno, "Failed to mount / as private: %m");
+
+ is_namespaced = true;
+
+ return 1;
+}
+
+static int setup_fake_filesystems(const char *runtime_dir) {
+ for (unsigned i = 0; i < ELEMENTSOF(fakefss); i++)
+ if (mount(runtime_dir, fakefss[i].target, NULL, MS_BIND, NULL) < 0) {
+ log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "Failed to mount %s: %m", fakefss[i].target);
+ if (!fakefss[i].ignore_mount_error)
+ return -errno;
+ }
+
+ return 0;
+}
+
+static int cleanup_fake_filesystems(const char *runtime_dir) {
+ for (unsigned i = 0; i < ELEMENTSOF(fakefss); i++)
+ if (umount(fakefss[i].target) < 0) {
+ log_full_errno(fakefss[i].ignore_mount_error ? LOG_DEBUG : LOG_ERR, errno, "Failed to umount %s: %m", fakefss[i].target);
+ if (!fakefss[i].ignore_mount_error)
+ return -errno;
+ }
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ _cleanup_(udev_rules_freep) struct udev_rules *rules = NULL;
+ _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
+ FILE *f = NULL;
+
+ if (!getenv("SYSTEMD_LOG_LEVEL")) {
+ log_set_max_level_realm(LOG_REALM_UDEV, LOG_CRIT);
+ log_set_max_level_realm(LOG_REALM_SYSTEMD, LOG_CRIT);
+ }
+
+ if (setup_mount_namespace() < 0)
+ return EXIT_TEST_SKIP;
+
+ assert_se(runtime_dir = setup_fake_runtime_dir());
+
+ assert_se(setup_fake_filesystems(runtime_dir) >= 0);
+ assert_se(mkdir_p("/etc/udev/rules.d", 0755) >= 0);
+ f = fopen("/etc/udev/rules.d/fuzz.rules", "we");
+ assert_se(f);
+ if (size != 0)
+ assert_se(fwrite(data, size, 1, f) == 1);
+ assert_se(fclose(f) == 0);
+ rules = udev_rules_new(RESOLVE_NAME_EARLY);
+
+ assert_se(cleanup_fake_filesystems(runtime_dir) >= 0);
+
+ return 0;
+}
diff --git a/src/fuzz/meson.build b/src/fuzz/meson.build
index 0af787b300..f628001a2a 100644
--- a/src/fuzz/meson.build
+++ b/src/fuzz/meson.build
@@ -97,6 +97,14 @@ fuzzers += [
libshared],
[]],
+ [['src/fuzz/fuzz-udev-rules.c'],
+ [libudev_core,
+ libudev_static,
+ libsystemd_network,
+ libshared],
+ [threads,
+ libacl]],
+
[['src/fuzz/fuzz-compress.c'],
[libshared],
[]],