Skip to content

Commit

Permalink
Merge pull request systemd#29611 from mrc0mmand/execute-serialize-fuzz
Browse files Browse the repository at this point in the history
test: add a fuzzer for exec_{serialize,deserialize}_invocation()
  • Loading branch information
bluca authored Oct 18, 2023
2 parents 81c1c38 + 892eb4d commit 47174dc
Show file tree
Hide file tree
Showing 8 changed files with 400 additions and 16 deletions.
30 changes: 16 additions & 14 deletions src/core/execute-serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -1261,22 +1261,24 @@ static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fd
if (r < 0)
return r;

if (p->n_socket_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-socket-fds", "%zu", p->n_socket_fds);
if (r < 0)
return r;
}
if (p->fds) {
if (p->n_socket_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-socket-fds", "%zu", p->n_socket_fds);
if (r < 0)
return r;
}

if (p->n_storage_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-storage-fds", "%zu", p->n_storage_fds);
if (r < 0)
return r;
}
if (p->n_storage_fds > 0) {
r = serialize_item_format(f, "exec-parameters-n-storage-fds", "%zu", p->n_storage_fds);
if (r < 0)
return r;
}

if (p->n_socket_fds + p->n_storage_fds > 0) {
r = serialize_fd_many(f, fds, "exec-parameters-fds", p->fds, p->n_socket_fds + p->n_storage_fds);
if (r < 0)
return r;
if (p->n_socket_fds + p->n_storage_fds > 0) {
r = serialize_fd_many(f, fds, "exec-parameters-fds", p->fds, p->n_socket_fds + p->n_storage_fds);
if (r < 0)
return r;
}
}

r = serialize_strv(f, "exec-parameters-fd-names", p->fd_names);
Expand Down
98 changes: 98 additions & 0 deletions src/core/fuzz-execute-serialize.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/* 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_serialized_done) ExecParameters params = {
.stdin_fd = -EBADF,
.stdout_fd = -EBADF,
.stderr_fd = -EBADF,
.exec_fd = -EBADF,
.user_lookup_fd = -EBADF,
.bpf_outer_map_fd = -EBADF,
};
_cleanup_(exec_context_done) ExecContext exec_context = {};
_cleanup_(cgroup_context_done) CGroupContext cgroup_context = {};
DynamicCreds dynamic_creds = {};
ExecCommand command = {};
ExecSharedRuntime shared = {
.netns_storage_socket = PIPE_EBADF,
.ipcns_storage_socket = PIPE_EBADF,
};
ExecRuntime runtime = {
.ephemeral_storage_socket = PIPE_EBADF,
.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, &params, &runtime, &cgroup_context);
(void) exec_serialize_invocation(f, fdset, &exec_context, &command, &params, &runtime, &cgroup_context);
(void) exec_deserialize_invocation(f, fdset, &exec_context, &command, &params, &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_outer_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;

/* We don't want to fill the logs with messages about parse errors.
* Disable most logging if not running standalone. */
if (!getenv("SYSTEMD_LOG_LEVEL")) {
log_set_max_level(LOG_CRIT);
log_set_target(LOG_TARGET_NULL);
}

assert_se(fdset = fdset_new());
assert_se(f = data_to_file(data, size));

exec_fuzz_one(f, fdset);

return 0;
}
7 changes: 7 additions & 0 deletions src/core/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,13 @@ executables += [
libshared
],
},
fuzz_template + {
'sources' : files('fuzz-execute-serialize.c'),
'link_with' : [
libcore,
libshared
],
},
]

in_files = [['system.conf', pkgconfigfiledir],
Expand Down
8 changes: 6 additions & 2 deletions src/shared/serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,9 @@ int serialize_item_hexmem(FILE *f, const char *key, const void *p, size_t l) {

assert(f);
assert(key);
assert(p || l == 0);

if (!p && l > 0)
return -EINVAL;

if (l == 0)
return 0;
Expand All @@ -230,7 +232,9 @@ int serialize_item_base64mem(FILE *f, const char *key, const void *p, size_t l)

assert(f);
assert(key);
assert(p || l == 0);

if (!p && l > 0)
return -EINVAL;

if (l == 0)
return 0;
Expand Down
3 changes: 3 additions & 0 deletions test/fuzz/fuzz-execute-serialize/crash-395e
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


exec-parameters-n-storage-fds=1782
3 changes: 3 additions & 0 deletions test/fuzz/fuzz-execute-serialize/crash-622a
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
exec-context-root-hash=0B12
exec-context-root-hash=0B1e�����exeec-unx-euucmask=10
exec-context-root-hash=0Be-22
Loading

0 comments on commit 47174dc

Please sign in to comment.