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_serialized_done
) ExecParameters params
= {
34 .user_lookup_fd
= -EBADF
,
35 .bpf_outer_map_fd
= -EBADF
,
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
,
45 ExecRuntime runtime
= {
46 .ephemeral_storage_socket
= PIPE_EBADF
,
48 .dynamic_creds
= &dynamic_creds
,
51 exec_context_init(&exec_context
);
52 cgroup_context_init(&cgroup_context
);
54 (void) exec_deserialize_invocation(f
, fdset
, &exec_context
, &command
, ¶ms
, &runtime
, &cgroup_context
);
55 (void) exec_serialize_invocation(f
, fdset
, &exec_context
, &command
, ¶ms
, &runtime
, &cgroup_context
);
56 (void) exec_deserialize_invocation(f
, fdset
, &exec_context
, &command
, ¶ms
, &runtime
, &cgroup_context
);
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
;
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
;
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
);
81 int LLVMFuzzerTestOneInput(const uint8_t *data
, size_t size
) {
82 _cleanup_fclose_
FILE *f
= NULL
;
83 _cleanup_fdset_free_ FDSet
*fdset
= NULL
;
87 assert_se(fdset
= fdset_new());
88 assert_se(f
= data_to_file(data
, size
));
90 exec_fuzz_one(f
, fdset
);