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
6 * 2) Collect some valid inputs:
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
17 * $ build-libfuzz/fuzz-execute-serialize test/fuzz/fuzz-execute-serialize
22 #include "alloc-util.h"
23 #include "execute-serialize.h"
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
,
38 ExecRuntime runtime
= {
39 .ephemeral_storage_socket
= EBADF_PAIR
,
41 .dynamic_creds
= &dynamic_creds
,
44 exec_context_init(&exec_context
);
45 cgroup_context_init(&cgroup_context
);
47 (void) exec_deserialize_invocation(f
, fdset
, &exec_context
, &command
, ¶ms
, &runtime
, &cgroup_context
);
48 (void) exec_serialize_invocation(f
, fdset
, &exec_context
, &command
, ¶ms
, &runtime
, &cgroup_context
);
49 (void) exec_deserialize_invocation(f
, fdset
, &exec_context
, &command
, ¶ms
, &runtime
, &cgroup_context
);
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
;
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
;
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
);
74 int LLVMFuzzerTestOneInput(const uint8_t *data
, size_t size
) {
75 _cleanup_fclose_
FILE *f
= NULL
;
76 _cleanup_fdset_free_ FDSet
*fdset
= NULL
;
78 if (outside_size_range(size
, 0, 128 * 1024))
83 assert_se(fdset
= fdset_new());
84 assert_se(f
= data_to_file(data
, size
));
86 exec_fuzz_one(f
, fdset
);