--- /dev/null
+/* 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, ¶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_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;
+}
--- /dev/null
+exec-context-environment=
+exec-context-environment-files=
+exec-context-pass-environment=
+exec-context-unset-environment=
+exec-context-working-directory=
+exec-context-root-directory=
+exec-context-root-image=
+exec-context-root-image-options=
+exec-context-root-verity=
+exec-context-root-hash-path=
+exec-context-root-hash-sig-path=
+exec-context-root-hash=
+exec-context-root-hash-sig=
+exec-context-root-ephemeral=
+exec-context-umask=
+exec-context-private-non-blocking=
+exec-context-private-mounts=
+exec-context-memory-ksm=
+exec-context-private-tmp=
+exec-context-private-devices=
+exec-context-protect-kernel-tunables=
+exec-context-protect-kernel-modules=
+exec-context-protect-kernel-logs=
+exec-context-protect-clock=
+exec-context-protect-control-groups=
+exec-context-private-network=
+exec-context-private-users=
+exec-context-private-ipc=
+exec-context-remove-ipc=
+exec-context-protect-home=
+exec-context-protect-system=
+exec-context-mount-api-vfs=
+exec-context-same-pgrp=
+exec-context-cpu-sched-reset-on-fork=
+exec-context-non-blocking=
+exec-context-ignore-sigpipe=
+exec-context-memory-deny-write-execute=
+exec-context-restrict-realtime=
+exec-context-restrict-suid-sgid=
+exec-context-keyring-mode=
+exec-context-protect-hostname=
+exec-context-protect-proc=
+exec-context-proc-subset=
+exec-context-runtime-directory-preserve-mode=
+exec-context-timeout-clean-usec=
+exec-context-nice=
+exec-context-working-directory-missing-ok=
+exec-context-working-directory-home=
+exec-context-oom-score-adjust=
+exec-context-coredump-filter=
+exec-context-ioprio=
+exec-context-cpu-scheduling-policy=
+exec-context-cpu-scheduling-priority=
+exec-context-cpu-scheduling-reset-on-fork=
+exec-context-cpu-affinity=
+exec-context-numa-mask=
+exec-context-numa-policy=
+exec-context-cpu-affinity-from-numa=
+exec-context-timer-slack-nsec=
+exec-context-std-input=
+exec-context-std-output=
+exec-context-std-error=
+exec-context-stdio-as-fds=
+exec-context-std-input-fd-name=
+exec-context-std-output-fd-name=
+exec-context-std-error-fd-name=
+exec-context-std-input-file=
+exec-context-std-output-file=
+exec-context-std-output-file-append=
+exec-context-std-output-file-truncate=
+exec-context-std-error-file=
+exec-context-std-error-file-append=
+exec-context-std-error-file-truncate=
+exec-context-stdin-data=
+exec-context-tty-path=
+exec-context-tty-reset=
+exec-context-tty-vhangup=
+exec-context-tty-vt-disallocate=
+exec-context-tty-rows=
+exec-context-tty-columns=
+exec-context-syslog-priority=
+exec-context-syslog-level-prefix=
+exec-context-syslog-identifier=
+exec-context-log-level-max=
+exec-context-log-ratelimit-interval-usec=
+exec-context-log-ratelimit-burst=
+exec-context-log-filter-allowed-patterns=
+exec-context-log-filter-denied-patterns=
+exec-context-log-extra-fields=
+exec-context-log-namespace=
+exec-context-secure-bits=
+exec-context-capability-bounding-set=
+exec-context-capability-ambient-set=
+exec-context-user=
+exec-context-group=
+exec-context-dynamic-user=
+exec-context-supplementary-groups=
+exec-context-set-login-environment=
+exec-context-pam-name=
+exec-context-read-write-paths=
+exec-context-read-only-paths=
+exec-context-inaccessible-paths=
+exec-context-exec-paths=
+exec-context-no-exec-paths=
+exec-context-exec-search-path=
+exec-context-mount-propagation-flag=
+exec-context-bind-read-only-path=
+exec-context-bind-path=
+exec-context-temporary-filesystems=
+exec-context-utmp-id=
+exec-context-utmp-mode=
+exec-context-no-new-privileges=
+exec-context-selinux-context-ignore=
+exec-context-apparmor-profile-ignore=
+exec-context-smack-process-label-ignore=
+exec-context-selinux-context=
+exec-context-apparmor-profile=
+exec-context-smack-process-label=
+exec-context-personality=
+exec-context-lock-personality=
+exec-context-syscall-filter=
+exec-context-syscall-archs=
+exec-context-syscall-errno=
+exec-context-syscall-allow-list=
+exec-context-syscall-log=
+exec-context-syscall-log-allow-list=
+exec-context-restrict-namespaces=
+exec-context-restrict-filesystems=
+exec-context-restrict-filesystems-allow-list=
+exec-context-address-families=
+exec-context-address-families-allow-list=
+exec-context-network-namespace-path=
+exec-context-ipc-namespace-path=
+exec-context-mount-image=
+exec-context-extension-image=
+exec-context-extension-directories=
+exec-context-set-credentials=
+exec-context-load-credentials=
+exec-context-import-credentials=
+exec-context-root-image-policy=
+exec-context-mount-image-policy=
+exec-context-extension-image-policy=
+
+exec-command-path=
+exec-command-argv=
+exec-command-flags=
+
+exec-parameters-runtime-scope=
+exec-parameters-environment=
+exec-parameters-n-socket-fds=
+exec-parameters-n-storage-fds=
+exec-parameters-fds=
+exec-parameters-fd-names=
+exec-parameters-flags=
+exec-parameters-selinux-context-net=
+exec-parameters-cgroup-supported=
+exec-parameters-cgroup-path=
+exec-parameters-cgroup-id=
+exec-parameters-received-credentials-directory=
+exec-parameters-received-encrypted-credentials-directory=
+exec-parameters-confirm-spawn=
+exec-parameters-shall-confirm-spawn=
+exec-parameters-watchdog-usec=
+exec-parameters-idle-pipe=
+exec-parameters-stdin-fd=
+exec-parameters-stdout-fd=
+exec-parameters-stderr-fd=
+exec-parameters-exec-fd=
+exec-parameters-bpf-outer-map-fd=
+exec-parameters-notify-socket=
+exec-parameters-open-file=
+exec-parameters-fallback-smack-process-label=
+exec-parameters-user-lookup-fd=
+exec-parameters-files-env=
+exec-parameters-unit-id=
+exec-parameters-invocation-id-string=
+
+exec-runtime-id=
+exec-runtime-tmp-dir=
+exec-runtime-var-tmp-dir=
+exec-runtime-netns-storage-socket=
+exec-runtime-ipcns-storage-socket=
+exec-runtime-dynamic-creds-user=
+exec-runtime-dynamic-creds-group=
+exec-runtime-dynamic-creds-group-copy=
+exec-runtime-ephemeral-copy=
+exec-runtime-ephemeral-storage-socket=
+
+exec-cgroup-context-cpu-accounting=
+exec-cgroup-context-io-accounting=
+exec-cgroup-context-block-io-accounting=
+exec-cgroup-context-memory-accounting=
+exec-cgroup-context-tasks-accounting=
+exec-cgroup-context-ip-accounting=
+exec-cgroup-context-memory-oom-group=
+exec-cgroup-context-cpu-weight=
+exec-cgroup-context-startup-cpu-weight=
+exec-cgroup-context-cpu-shares=
+exec-cgroup-context-startup-cpu-shares=
+exec-cgroup-context-cpu-quota-per-sec-usec=
+exec-cgroup-context-cpu-quota-period-usec=
+exec-cgroup-context-allowed-cpus=
+exec-cgroup-context-startup-allowed-cpus=
+exec-cgroup-context-allowed-memory-nodes=
+exec-cgroup-context-startup-allowed-memory-nodes=
+exec-cgroup-context-io-weight=
+exec-cgroup-context-startup-io-weight=
+exec-cgroup-context-block-io-weight=
+exec-cgroup-context-startup-block-io-weight=
+exec-cgroup-context-default-memory-min=
+exec-cgroup-context-default-memory-low=
+exec-cgroup-context-memory-min=
+exec-cgroup-context-memory-low=
+exec-cgroup-context-startup-memory-low=
+exec-cgroup-context-memory-high=
+exec-cgroup-context-startup-memory-high=
+exec-cgroup-context-memory-max=
+exec-cgroup-context-startup-memory-max=
+exec-cgroup-context-memory-swap-max=
+exec-cgroup-context-startup-memory-swap-max=
+exec-cgroup-context-memory-zswap-max=
+exec-cgroup-context-startup-memory-zswap-max=
+exec-cgroup-context-memory-limit=
+exec-cgroup-context-tasks-max-value=
+exec-cgroup-context-tasks-max-scale=
+exec-cgroup-context-default-memory-min-set=
+exec-cgroup-context-default-memory-low-set=
+exec-cgroup-context-default-startup-memory-low-set=
+exec-cgroup-context-memory-min-set=
+exec-cgroup-context-memory-low-set=
+exec-cgroup-context-startup-memory-low-set=
+exec-cgroup-context-startup-memory-high-set=
+exec-cgroup-context-startup-memory-max-set=
+exec-cgroup-context-startup-memory-swap-max-set=
+exec-cgroup-context-startup-memory-zswap-max-set=
+exec-cgroup-context-device-policy=
+exec-cgroup-context-disable-controllers=
+exec-cgroup-context-delegate-controllers=
+exec-cgroup-context-delegate=
+exec-cgroup-context-managed-oom-swap=
+exec-cgroup-context-managed-oom-memory-pressure=
+exec-cgroup-context-managed-oom-memory-pressure-limit=
+exec-cgroup-context-managed-oom-preference=
+exec-cgroup-context-memory-pressure-watch=
+exec-cgroup-context-delegate-subgroup=
+exec-cgroup-context-memory-pressure-threshold-usec=
+exec-cgroup-context-device-allow=
+exec-cgroup-context-io-device-weight=
+exec-cgroup-context-io-device-latency-target-usec=
+exec-cgroup-context-block-io-device-weight=
+exec-cgroup-context-block-io-read-bandwidth=
+exec-cgroup-context-block-io-write-bandwidth=
+exec-cgroup-context-ip-address-allow=
+exec-cgroup-context-ip-address-deny=
+exec-cgroup-context-ip-address-allow-reduced=
+exec-cgroup-context-ip-address-deny-reduced=
+exec-cgroup-context-ip-ingress-filter-path=
+exec-cgroup-context-ip-egress-filter-path=
+exec-cgroup-context-bpf-program=
+exec-cgroup-context-socket-bind-allow=
+exec-cgroup-context-socket-bind-deny=
+exec-cgroup-context-restrict-network-interfaces=
+exec-cgroup-context-restrict-network-interfaces-is-allow-list=
+