]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/fuzz-execute-serialize.c
core: align table
[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_deep_clear) ExecParameters params = EXEC_PARAMETERS_INIT(/* flags= */ 0);
30 _cleanup_(exec_context_done) ExecContext exec_context = {};
31 _cleanup_(cgroup_context_done) CGroupContext cgroup_context = {};
32 DynamicCreds dynamic_creds = {};
33 ExecCommand command = {};
34 ExecSharedRuntime shared = {
35 .netns_storage_socket = EBADF_PAIR,
36 .ipcns_storage_socket = EBADF_PAIR,
37 };
38 ExecRuntime runtime = {
39 .ephemeral_storage_socket = EBADF_PAIR,
40 .shared = &shared,
41 .dynamic_creds = &dynamic_creds,
42 };
43
44 exec_context_init(&exec_context);
45 cgroup_context_init(&cgroup_context);
46
47 (void) exec_deserialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
48 (void) exec_serialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
49 (void) exec_deserialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
50
51 /* We definitely didn't provide valid FDs during deserialization, so
52 * wipe the FDs before exec_params_serialized_clear() kicks in, otherwise
53 * we'll hit the assert in safe_close() */
54 params.stdin_fd = -EBADF;
55 params.stdout_fd = -EBADF;
56 params.stderr_fd = -EBADF;
57 params.exec_fd = -EBADF;
58 params.user_lookup_fd = -EBADF;
59 params.bpf_restrict_fs_map_fd = -EBADF;
60 if (!params.fds)
61 params.n_socket_fds = params.n_storage_fds = 0;
62 for (size_t i = 0; params.fds && i < params.n_socket_fds + params.n_storage_fds; i++)
63 params.fds[i] = -EBADF;
64
65 exec_command_done_array(&command, /* n= */ 1);
66 exec_shared_runtime_done(&shared);
67 if (dynamic_creds.group != dynamic_creds.user)
68 dynamic_user_free(dynamic_creds.group);
69 dynamic_user_free(dynamic_creds.user);
70 free(runtime.ephemeral_copy);
71 safe_close_pair(runtime.ephemeral_storage_socket);
72 }
73
74 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
75 _cleanup_fclose_ FILE *f = NULL;
76 _cleanup_fdset_free_ FDSet *fdset = NULL;
77
78 if (outside_size_range(size, 0, 128 * 1024))
79 return 0;
80
81 fuzz_setup_logging();
82
83 assert_se(fdset = fdset_new());
84 assert_se(f = data_to_file(data, size));
85
86 exec_fuzz_one(f, fdset);
87
88 return 0;
89 }