1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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, ¶ms, &runtime, &cgroup_context);
(void) exec_serialize_invocation(f, fdset, &exec_context, &command, ¶ms, &runtime, &cgroup_context);
(void) exec_deserialize_invocation(f, fdset, &exec_context, &command, ¶ms, &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_restrict_fs_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;
}
|