]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/fuzz-execute-serialize.c
fuzz: unify logging setup
[thirdparty/systemd.git] / src / core / fuzz-execute-serialize.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /* Notes on how to run the fuzzer manually:
3 * 1) Build the fuzzers with LLVM's libFuzzer and ASan+UBSan:
4 * $ CC=clang CXX=clang++ meson build-libfuzz -Db_sanitize=address,undefined -Dllvm-fuzz=true -Db_lundef=false
5 *
6 * 2) Collect some valid inputs:
7 *
8 * OUT=test/fuzz/fuzz-execute-serialize/initial
9 * for section in context command parameters runtime cgroup; do
10 * awk "match(\$0, /startswith\\(.+, \"(exec-${section}-[^\"]+=)\"/, m) { print m[1]; }" \
11 * src/core/execute-serialize.c >>"$OUT"
12 * # Each "section" is delimited by an empty line
13 * echo >>"$OUT"
14 * done
15 *
16 * 3) Run the fuzzer:
17 * $ build-libfuzz/fuzz-execute-serialize test/fuzz/fuzz-execute-serialize
18 */
19
20 #include <stdio.h>
21
22 #include "alloc-util.h"
23 #include "execute-serialize.h"
24 #include "fd-util.h"
25 #include "fuzz.h"
26 #include "service.h"
27
28 static void exec_fuzz_one(FILE *f, FDSet *fdset) {
29 _cleanup_(exec_params_serialized_done) ExecParameters params = {
30 .stdin_fd = -EBADF,
31 .stdout_fd = -EBADF,
32 .stderr_fd = -EBADF,
33 .exec_fd = -EBADF,
34 .user_lookup_fd = -EBADF,
35 .bpf_outer_map_fd = -EBADF,
36 };
37 _cleanup_(exec_context_done) ExecContext exec_context = {};
38 _cleanup_(cgroup_context_done) CGroupContext cgroup_context = {};
39 DynamicCreds dynamic_creds = {};
40 ExecCommand command = {};
41 ExecSharedRuntime shared = {
42 .netns_storage_socket = PIPE_EBADF,
43 .ipcns_storage_socket = PIPE_EBADF,
44 };
45 ExecRuntime runtime = {
46 .ephemeral_storage_socket = PIPE_EBADF,
47 .shared = &shared,
48 .dynamic_creds = &dynamic_creds,
49 };
50
51 exec_context_init(&exec_context);
52 cgroup_context_init(&cgroup_context);
53
54 (void) exec_deserialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
55 (void) exec_serialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
56 (void) exec_deserialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
57
58 /* We definitely didn't provide valid FDs during deserialization, so
59 * wipe the FDs before exec_params_serialized_clear() kicks in, otherwise
60 * we'll hit the assert in safe_close() */
61 params.stdin_fd = -EBADF;
62 params.stdout_fd = -EBADF;
63 params.stderr_fd = -EBADF;
64 params.exec_fd = -EBADF;
65 params.user_lookup_fd = -EBADF;
66 params.bpf_outer_map_fd = -EBADF;
67 if (!params.fds)
68 params.n_socket_fds = params.n_storage_fds = 0;
69 for (size_t i = 0; params.fds && i < params.n_socket_fds + params.n_storage_fds; i++)
70 params.fds[i] = -EBADF;
71
72 exec_command_done_array(&command, /* n= */ 1);
73 exec_shared_runtime_done(&shared);
74 if (dynamic_creds.group != dynamic_creds.user)
75 dynamic_user_free(dynamic_creds.group);
76 dynamic_user_free(dynamic_creds.user);
77 free(runtime.ephemeral_copy);
78 safe_close_pair(runtime.ephemeral_storage_socket);
79 }
80
81 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
82 _cleanup_fclose_ FILE *f = NULL;
83 _cleanup_fdset_free_ FDSet *fdset = NULL;
84
85 fuzz_setup_logging();
86
87 assert_se(fdset = fdset_new());
88 assert_se(f = data_to_file(data, size));
89
90 exec_fuzz_one(f, fdset);
91
92 return 0;
93 }