summaryrefslogtreecommitdiffstats
path: root/src/core/fuzz-execute-serialize.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:49:52 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:49:52 +0000
commit55944e5e40b1be2afc4855d8d2baf4b73d1876b5 (patch)
tree33f869f55a1b149e9b7c2b7e201867ca5dd52992 /src/core/fuzz-execute-serialize.c
parentInitial commit. (diff)
downloadsystemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.tar.xz
systemd-55944e5e40b1be2afc4855d8d2baf4b73d1876b5.zip
Adding upstream version 255.4.upstream/255.4
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/core/fuzz-execute-serialize.c')
-rw-r--r--src/core/fuzz-execute-serialize.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/src/core/fuzz-execute-serialize.c b/src/core/fuzz-execute-serialize.c
new file mode 100644
index 0000000..6069efd
--- /dev/null
+++ b/src/core/fuzz-execute-serialize.c
@@ -0,0 +1,89 @@
+/* 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_deep_clear) ExecParameters params = EXEC_PARAMETERS_INIT(/* flags= */ 0);
+ _cleanup_(exec_context_done) ExecContext exec_context = {};
+ _cleanup_(cgroup_context_done) CGroupContext cgroup_context = {};
+ DynamicCreds dynamic_creds = {};
+ ExecCommand command = {};
+ ExecSharedRuntime shared = {
+ .netns_storage_socket = EBADF_PAIR,
+ .ipcns_storage_socket = EBADF_PAIR,
+ };
+ ExecRuntime runtime = {
+ .ephemeral_storage_socket = EBADF_PAIR,
+ .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;
+
+ if (outside_size_range(size, 0, 128 * 1024))
+ return 0;
+
+ fuzz_setup_logging();
+
+ assert_se(fdset = fdset_new());
+ assert_se(f = data_to_file(data, size));
+
+ exec_fuzz_one(f, fdset);
+
+ return 0;
+}