]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: add a fuzzer for exec_{serialize,deserialize}_invocation()
authorFrantisek Sumsal <frantisek@sumsal.cz>
Fri, 28 Jul 2023 08:33:08 +0000 (10:33 +0200)
committerFrantisek Sumsal <frantisek@sumsal.cz>
Wed, 18 Oct 2023 20:44:16 +0000 (22:44 +0200)
src/core/fuzz-execute-serialize.c [new file with mode: 0644]
src/core/meson.build
test/fuzz/fuzz-execute-serialize/initial [new file with mode: 0644]
test/fuzz/fuzz-execute-serialize/mount-images [new file with mode: 0644]

diff --git a/src/core/fuzz-execute-serialize.c b/src/core/fuzz-execute-serialize.c
new file mode 100644 (file)
index 0000000..140b2b8
--- /dev/null
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/* Notes on how to run the fuzzer manually:
+ *  1) Build the fuzzers with LLVM's libFuzzer and ASan+UBSan:
+ *    $ CC=clang CXX=clang++ meson build-libfuzz -Db_sanitize=address,undefined -Dllvm-fuzz=true -Db_lundef=false
+ *
+ *  2) Collect some valid inputs:
+ *
+ * OUT=test/fuzz/fuzz-execute-serialize/initial
+ * for section in context command parameters runtime cgroup; do
+ *     awk "match(\$0, /startswith\\(.+, \"(exec-${section}-[^\"]+=)\"/, m) { print m[1]; }" \
+ *         src/core/execute-serialize.c >>"$OUT"
+ *     # Each "section" is delimited by an empty line
+ *     echo >>"$OUT"
+ * done
+ *
+ *  3) Run the fuzzer:
+ *    $ build-libfuzz/fuzz-execute-serialize test/fuzz/fuzz-execute-serialize
+ */
+
+#include <stdio.h>
+
+#include "alloc-util.h"
+#include "execute-serialize.h"
+#include "fd-util.h"
+#include "fuzz.h"
+#include "service.h"
+
+static void exec_fuzz_one(FILE *f, FDSet *fdset) {
+        _cleanup_(exec_params_serialized_done) ExecParameters params = {
+                .stdin_fd         = -EBADF,
+                .stdout_fd        = -EBADF,
+                .stderr_fd        = -EBADF,
+                .exec_fd          = -EBADF,
+                .user_lookup_fd   = -EBADF,
+                .bpf_outer_map_fd = -EBADF,
+        };
+        _cleanup_(exec_context_done) ExecContext exec_context = {};
+        _cleanup_(cgroup_context_done) CGroupContext cgroup_context = {};
+        DynamicCreds dynamic_creds = {};
+        ExecCommand command = {};
+        ExecSharedRuntime shared = {
+                .netns_storage_socket = PIPE_EBADF,
+                .ipcns_storage_socket = PIPE_EBADF,
+        };
+        ExecRuntime runtime = {
+                .ephemeral_storage_socket = PIPE_EBADF,
+                .shared = &shared,
+                .dynamic_creds = &dynamic_creds,
+        };
+
+        exec_context_init(&exec_context);
+        cgroup_context_init(&cgroup_context);
+
+        (void) exec_deserialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
+        (void) exec_serialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
+        (void) exec_deserialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
+
+        /* We definitely didn't provide valid FDs during deserialization, so
+         * wipe the FDs before exec_params_serialized_clear() kicks in, otherwise
+         * we'll hit the assert in safe_close() */
+        params.stdin_fd = -EBADF;
+        params.stdout_fd = -EBADF;
+        params.stderr_fd = -EBADF;
+        params.exec_fd = -EBADF;
+        params.user_lookup_fd = -EBADF;
+        params.bpf_outer_map_fd = -EBADF;
+        if (!params.fds)
+                params.n_socket_fds = params.n_storage_fds = 0;
+        for (size_t i = 0; params.fds && i < params.n_socket_fds + params.n_storage_fds; i++)
+                params.fds[i] = -EBADF;
+
+        exec_command_done_array(&command, /* n= */ 1);
+        exec_shared_runtime_done(&shared);
+        if (dynamic_creds.group != dynamic_creds.user)
+                dynamic_user_free(dynamic_creds.group);
+        dynamic_user_free(dynamic_creds.user);
+        free(runtime.ephemeral_copy);
+        safe_close_pair(runtime.ephemeral_storage_socket);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+        _cleanup_fclose_ FILE *f = NULL;
+        _cleanup_fdset_free_ FDSet *fdset = NULL;
+
+        /* We don't want to fill the logs with messages about parse errors.
+         * Disable most logging if not running standalone. */
+        if (!getenv("SYSTEMD_LOG_LEVEL")) {
+                log_set_max_level(LOG_CRIT);
+                log_set_target(LOG_TARGET_NULL);
+        }
+
+        assert_se(fdset = fdset_new());
+        assert_se(f = data_to_file(data, size));
+
+        exec_fuzz_one(f, fdset);
+
+        return 0;
+}
index ce20b51aec136254c7bee46a1ee34cbfaa85a5e3..7701d3de0a35f4aa43a99a4c2d69fe48c36661ec 100644 (file)
@@ -192,6 +192,13 @@ executables += [
                         libshared
                 ],
         },
+        fuzz_template + {
+                'sources' : files('fuzz-execute-serialize.c'),
+                'link_with' : [
+                        libcore,
+                        libshared
+                ],
+        },
 ]
 
 in_files = [['system.conf',                     pkgconfigfiledir],
diff --git a/test/fuzz/fuzz-execute-serialize/initial b/test/fuzz/fuzz-execute-serialize/initial
new file mode 100644 (file)
index 0000000..403cf08
--- /dev/null
@@ -0,0 +1,264 @@
+exec-context-environment=
+exec-context-environment-files=
+exec-context-pass-environment=
+exec-context-unset-environment=
+exec-context-working-directory=
+exec-context-root-directory=
+exec-context-root-image=
+exec-context-root-image-options=
+exec-context-root-verity=
+exec-context-root-hash-path=
+exec-context-root-hash-sig-path=
+exec-context-root-hash=
+exec-context-root-hash-sig=
+exec-context-root-ephemeral=
+exec-context-umask=
+exec-context-private-non-blocking=
+exec-context-private-mounts=
+exec-context-memory-ksm=
+exec-context-private-tmp=
+exec-context-private-devices=
+exec-context-protect-kernel-tunables=
+exec-context-protect-kernel-modules=
+exec-context-protect-kernel-logs=
+exec-context-protect-clock=
+exec-context-protect-control-groups=
+exec-context-private-network=
+exec-context-private-users=
+exec-context-private-ipc=
+exec-context-remove-ipc=
+exec-context-protect-home=
+exec-context-protect-system=
+exec-context-mount-api-vfs=
+exec-context-same-pgrp=
+exec-context-cpu-sched-reset-on-fork=
+exec-context-non-blocking=
+exec-context-ignore-sigpipe=
+exec-context-memory-deny-write-execute=
+exec-context-restrict-realtime=
+exec-context-restrict-suid-sgid=
+exec-context-keyring-mode=
+exec-context-protect-hostname=
+exec-context-protect-proc=
+exec-context-proc-subset=
+exec-context-runtime-directory-preserve-mode=
+exec-context-timeout-clean-usec=
+exec-context-nice=
+exec-context-working-directory-missing-ok=
+exec-context-working-directory-home=
+exec-context-oom-score-adjust=
+exec-context-coredump-filter=
+exec-context-ioprio=
+exec-context-cpu-scheduling-policy=
+exec-context-cpu-scheduling-priority=
+exec-context-cpu-scheduling-reset-on-fork=
+exec-context-cpu-affinity=
+exec-context-numa-mask=
+exec-context-numa-policy=
+exec-context-cpu-affinity-from-numa=
+exec-context-timer-slack-nsec=
+exec-context-std-input=
+exec-context-std-output=
+exec-context-std-error=
+exec-context-stdio-as-fds=
+exec-context-std-input-fd-name=
+exec-context-std-output-fd-name=
+exec-context-std-error-fd-name=
+exec-context-std-input-file=
+exec-context-std-output-file=
+exec-context-std-output-file-append=
+exec-context-std-output-file-truncate=
+exec-context-std-error-file=
+exec-context-std-error-file-append=
+exec-context-std-error-file-truncate=
+exec-context-stdin-data=
+exec-context-tty-path=
+exec-context-tty-reset=
+exec-context-tty-vhangup=
+exec-context-tty-vt-disallocate=
+exec-context-tty-rows=
+exec-context-tty-columns=
+exec-context-syslog-priority=
+exec-context-syslog-level-prefix=
+exec-context-syslog-identifier=
+exec-context-log-level-max=
+exec-context-log-ratelimit-interval-usec=
+exec-context-log-ratelimit-burst=
+exec-context-log-filter-allowed-patterns=
+exec-context-log-filter-denied-patterns=
+exec-context-log-extra-fields=
+exec-context-log-namespace=
+exec-context-secure-bits=
+exec-context-capability-bounding-set=
+exec-context-capability-ambient-set=
+exec-context-user=
+exec-context-group=
+exec-context-dynamic-user=
+exec-context-supplementary-groups=
+exec-context-set-login-environment=
+exec-context-pam-name=
+exec-context-read-write-paths=
+exec-context-read-only-paths=
+exec-context-inaccessible-paths=
+exec-context-exec-paths=
+exec-context-no-exec-paths=
+exec-context-exec-search-path=
+exec-context-mount-propagation-flag=
+exec-context-bind-read-only-path=
+exec-context-bind-path=
+exec-context-temporary-filesystems=
+exec-context-utmp-id=
+exec-context-utmp-mode=
+exec-context-no-new-privileges=
+exec-context-selinux-context-ignore=
+exec-context-apparmor-profile-ignore=
+exec-context-smack-process-label-ignore=
+exec-context-selinux-context=
+exec-context-apparmor-profile=
+exec-context-smack-process-label=
+exec-context-personality=
+exec-context-lock-personality=
+exec-context-syscall-filter=
+exec-context-syscall-archs=
+exec-context-syscall-errno=
+exec-context-syscall-allow-list=
+exec-context-syscall-log=
+exec-context-syscall-log-allow-list=
+exec-context-restrict-namespaces=
+exec-context-restrict-filesystems=
+exec-context-restrict-filesystems-allow-list=
+exec-context-address-families=
+exec-context-address-families-allow-list=
+exec-context-network-namespace-path=
+exec-context-ipc-namespace-path=
+exec-context-mount-image=
+exec-context-extension-image=
+exec-context-extension-directories=
+exec-context-set-credentials=
+exec-context-load-credentials=
+exec-context-import-credentials=
+exec-context-root-image-policy=
+exec-context-mount-image-policy=
+exec-context-extension-image-policy=
+
+exec-command-path=
+exec-command-argv=
+exec-command-flags=
+
+exec-parameters-runtime-scope=
+exec-parameters-environment=
+exec-parameters-n-socket-fds=
+exec-parameters-n-storage-fds=
+exec-parameters-fds=
+exec-parameters-fd-names=
+exec-parameters-flags=
+exec-parameters-selinux-context-net=
+exec-parameters-cgroup-supported=
+exec-parameters-cgroup-path=
+exec-parameters-cgroup-id=
+exec-parameters-received-credentials-directory=
+exec-parameters-received-encrypted-credentials-directory=
+exec-parameters-confirm-spawn=
+exec-parameters-shall-confirm-spawn=
+exec-parameters-watchdog-usec=
+exec-parameters-idle-pipe=
+exec-parameters-stdin-fd=
+exec-parameters-stdout-fd=
+exec-parameters-stderr-fd=
+exec-parameters-exec-fd=
+exec-parameters-bpf-outer-map-fd=
+exec-parameters-notify-socket=
+exec-parameters-open-file=
+exec-parameters-fallback-smack-process-label=
+exec-parameters-user-lookup-fd=
+exec-parameters-files-env=
+exec-parameters-unit-id=
+exec-parameters-invocation-id-string=
+
+exec-runtime-id=
+exec-runtime-tmp-dir=
+exec-runtime-var-tmp-dir=
+exec-runtime-netns-storage-socket=
+exec-runtime-ipcns-storage-socket=
+exec-runtime-dynamic-creds-user=
+exec-runtime-dynamic-creds-group=
+exec-runtime-dynamic-creds-group-copy=
+exec-runtime-ephemeral-copy=
+exec-runtime-ephemeral-storage-socket=
+
+exec-cgroup-context-cpu-accounting=
+exec-cgroup-context-io-accounting=
+exec-cgroup-context-block-io-accounting=
+exec-cgroup-context-memory-accounting=
+exec-cgroup-context-tasks-accounting=
+exec-cgroup-context-ip-accounting=
+exec-cgroup-context-memory-oom-group=
+exec-cgroup-context-cpu-weight=
+exec-cgroup-context-startup-cpu-weight=
+exec-cgroup-context-cpu-shares=
+exec-cgroup-context-startup-cpu-shares=
+exec-cgroup-context-cpu-quota-per-sec-usec=
+exec-cgroup-context-cpu-quota-period-usec=
+exec-cgroup-context-allowed-cpus=
+exec-cgroup-context-startup-allowed-cpus=
+exec-cgroup-context-allowed-memory-nodes=
+exec-cgroup-context-startup-allowed-memory-nodes=
+exec-cgroup-context-io-weight=
+exec-cgroup-context-startup-io-weight=
+exec-cgroup-context-block-io-weight=
+exec-cgroup-context-startup-block-io-weight=
+exec-cgroup-context-default-memory-min=
+exec-cgroup-context-default-memory-low=
+exec-cgroup-context-memory-min=
+exec-cgroup-context-memory-low=
+exec-cgroup-context-startup-memory-low=
+exec-cgroup-context-memory-high=
+exec-cgroup-context-startup-memory-high=
+exec-cgroup-context-memory-max=
+exec-cgroup-context-startup-memory-max=
+exec-cgroup-context-memory-swap-max=
+exec-cgroup-context-startup-memory-swap-max=
+exec-cgroup-context-memory-zswap-max=
+exec-cgroup-context-startup-memory-zswap-max=
+exec-cgroup-context-memory-limit=
+exec-cgroup-context-tasks-max-value=
+exec-cgroup-context-tasks-max-scale=
+exec-cgroup-context-default-memory-min-set=
+exec-cgroup-context-default-memory-low-set=
+exec-cgroup-context-default-startup-memory-low-set=
+exec-cgroup-context-memory-min-set=
+exec-cgroup-context-memory-low-set=
+exec-cgroup-context-startup-memory-low-set=
+exec-cgroup-context-startup-memory-high-set=
+exec-cgroup-context-startup-memory-max-set=
+exec-cgroup-context-startup-memory-swap-max-set=
+exec-cgroup-context-startup-memory-zswap-max-set=
+exec-cgroup-context-device-policy=
+exec-cgroup-context-disable-controllers=
+exec-cgroup-context-delegate-controllers=
+exec-cgroup-context-delegate=
+exec-cgroup-context-managed-oom-swap=
+exec-cgroup-context-managed-oom-memory-pressure=
+exec-cgroup-context-managed-oom-memory-pressure-limit=
+exec-cgroup-context-managed-oom-preference=
+exec-cgroup-context-memory-pressure-watch=
+exec-cgroup-context-delegate-subgroup=
+exec-cgroup-context-memory-pressure-threshold-usec=
+exec-cgroup-context-device-allow=
+exec-cgroup-context-io-device-weight=
+exec-cgroup-context-io-device-latency-target-usec=
+exec-cgroup-context-block-io-device-weight=
+exec-cgroup-context-block-io-read-bandwidth=
+exec-cgroup-context-block-io-write-bandwidth=
+exec-cgroup-context-ip-address-allow=
+exec-cgroup-context-ip-address-deny=
+exec-cgroup-context-ip-address-allow-reduced=
+exec-cgroup-context-ip-address-deny-reduced=
+exec-cgroup-context-ip-ingress-filter-path=
+exec-cgroup-context-ip-egress-filter-path=
+exec-cgroup-context-bpf-program=
+exec-cgroup-context-socket-bind-allow=
+exec-cgroup-context-socket-bind-deny=
+exec-cgroup-context-restrict-network-interfaces=
+exec-cgroup-context-restrict-network-interfaces-is-allow-list=
+
diff --git a/test/fuzz/fuzz-execute-serialize/mount-images b/test/fuzz/fuzz-execute-serialize/mount-images
new file mode 100644 (file)
index 0000000..6ca8fa8
--- /dev/null
@@ -0,0 +1,3 @@
+exec-context-mount-image=/dev/foo / root:suid
+exec-context-mount-image=/tmp/tmp.RcqHuV/minimal_0.gpt /run/img1 root:noatime
+exec-context-mount-image=/tmp/tmp.RcqHuV/minimal_0.gpt /run/img1 root:noatime home:relatime