From: Frantisek Sumsal Date: Fri, 28 Jul 2023 08:33:08 +0000 (+0200) Subject: test: add a fuzzer for exec_{serialize,deserialize}_invocation() X-Git-Tag: v255-rc1~208^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=81c4be64daa2f000875f636dd23ccf6f950a19c0;p=thirdparty%2Fsystemd.git test: add a fuzzer for exec_{serialize,deserialize}_invocation() --- diff --git a/src/core/fuzz-execute-serialize.c b/src/core/fuzz-execute-serialize.c new file mode 100644 index 00000000000..140b2b8250f --- /dev/null +++ b/src/core/fuzz-execute-serialize.c @@ -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 + +#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; +} diff --git a/src/core/meson.build b/src/core/meson.build index ce20b51aec1..7701d3de0a3 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -192,6 +192,13 @@ executables += [ libshared ], }, + fuzz_template + { + 'sources' : files('fuzz-execute-serialize.c'), + 'link_with' : [ + libcore, + libshared + ], + }, ] in_files = [['system.conf', pkgconfigfiledir], diff --git a/test/fuzz/fuzz-execute-serialize/initial b/test/fuzz/fuzz-execute-serialize/initial new file mode 100644 index 00000000000..403cf085a4a --- /dev/null +++ b/test/fuzz/fuzz-execute-serialize/initial @@ -0,0 +1,264 @@ +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= + diff --git a/test/fuzz/fuzz-execute-serialize/mount-images b/test/fuzz/fuzz-execute-serialize/mount-images new file mode 100644 index 00000000000..6ca8fa82013 --- /dev/null +++ b/test/fuzz/fuzz-execute-serialize/mount-images @@ -0,0 +1,3 @@ +exec-context-mount-image=/dev/foo / root:suid +exec-context-mount-image=/tmp/tmp.RcqHuV/minimal_0.gpt /run/img1 root:noatime +exec-context-mount-image=/tmp/tmp.RcqHuV/minimal_0.gpt /run/img1 root:noatime home:relatime