diff --git a/src/core/execute-serialize.c b/src/core/execute-serialize.c index 342883994a..56c4f4da8a 100644 --- a/src/core/execute-serialize.c +++ b/src/core/execute-serialize.c @@ -1244,7 +1244,7 @@ static bool exec_parameters_is_idle_pipe_set(const ExecParameters *p) { p->idle_pipe[3] >= 0; } -static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fds) { +static int exec_parameters_serialize(const ExecParameters *p, const ExecContext *c, FILE *f, FDSet *fds) { int r; assert(f); @@ -1274,11 +1274,9 @@ static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fd 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_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); @@ -1351,31 +1349,23 @@ static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fd return r; } - if (p->stdin_fd >= 0) { - r = serialize_fd(f, fds, "exec-parameters-stdin-fd", p->stdin_fd); - if (r < 0) - return r; - } + r = serialize_fd(f, fds, "exec-parameters-stdin-fd", p->stdin_fd); + if (r < 0) + return r; - if (p->stdout_fd >= 0) { - r = serialize_fd(f, fds, "exec-parameters-stdout-fd", p->stdout_fd); - if (r < 0) - return r; - } + r = serialize_fd(f, fds, "exec-parameters-stdout-fd", p->stdout_fd); + if (r < 0) + return r; - if (p->stderr_fd >= 0) { - r = serialize_fd(f, fds, "exec-parameters-stderr-fd", p->stderr_fd); - if (r < 0) - return r; - } + r = serialize_fd(f, fds, "exec-parameters-stderr-fd", p->stderr_fd); + if (r < 0) + return r; - if (p->exec_fd >= 0) { - r = serialize_fd(f, fds, "exec-parameters-exec-fd", p->exec_fd); - if (r < 0) - return r; - } + r = serialize_fd(f, fds, "exec-parameters-exec-fd", p->exec_fd); + if (r < 0) + return r; - if (p->bpf_outer_map_fd >= 0) { + if (c && exec_context_restrict_filesystems_set(c)) { r = serialize_fd(f, fds, "exec-parameters-bpf-outer-map-fd", p->bpf_outer_map_fd); if (r < 0) return r; @@ -1401,11 +1391,9 @@ static int exec_parameters_serialize(const ExecParameters *p, FILE *f, FDSet *fd if (r < 0) return r; - if (p->user_lookup_fd >= 0) { - r = serialize_fd(f, fds, "exec-parameters-user-lookup-fd", p->user_lookup_fd); - if (r < 0) - return r; - } + r = serialize_fd(f, fds, "exec-parameters-user-lookup-fd", p->user_lookup_fd); + if (r < 0) + return r; r = serialize_strv(f, "exec-parameters-files-env", p->files_env); if (r < 0) @@ -3860,7 +3848,7 @@ int exec_serialize_invocation( if (r < 0) return log_debug_errno(r, "Failed to serialize command: %m"); - r = exec_parameters_serialize(p, f, fds); + r = exec_parameters_serialize(p, ctx, f, fds); if (r < 0) return log_debug_errno(r, "Failed to serialize parameters: %m"); diff --git a/test/units/testsuite-07.exec-context.sh b/test/units/testsuite-07.exec-context.sh index b4118d2fe8..10b425359d 100755 --- a/test/units/testsuite-07.exec-context.sh +++ b/test/units/testsuite-07.exec-context.sh @@ -4,6 +4,9 @@ set -eux set -o pipefail +# shellcheck source=test/units/util.sh +. "$(dirname "$0")"/util.sh + # Make sure the unit's exec context matches its configuration # See: https://github.com/systemd/systemd/pull/29552 @@ -284,6 +287,34 @@ systemd-run --wait --pipe "${ARGUMENTS[@]}" \ ulimit -R || exit 0; : RTTIME; [[ $(ulimit -SR) -eq 666666 ]]; [[ $(ulimit -HR) -eq 666666 ]];' +# RestrictFileSystems= +# +# Note: running instrumented binaries requires at least /proc to be accessible, so let's +# skip the test when we're running under sanitizers +if [[ ! -v ASAN_OPTIONS ]] && systemctl --version | grep "+BPF_FRAMEWORK" && kernel_supports_lsm bpf; then + ROOTFS="$(df --output=fstype /usr/bin | sed --quiet 2p)" + systemd-run --wait --pipe -p RestrictFileSystems="" ls / + systemd-run --wait --pipe -p RestrictFileSystems="$ROOTFS foo bar" ls / + (! systemd-run --wait --pipe -p RestrictFileSystems="$ROOTFS" ls /proc) + (! systemd-run --wait --pipe -p RestrictFileSystems="foo" ls /) + systemd-run --wait --pipe -p RestrictFileSystems="$ROOTFS foo bar baz proc" ls /proc + systemd-run --wait --pipe -p RestrictFileSystems="$ROOTFS @foo @basic-api" ls /proc + systemd-run --wait --pipe -p RestrictFileSystems="$ROOTFS @foo @basic-api" ls /sys/fs/cgroup + + systemd-run --wait --pipe -p RestrictFileSystems="~" ls / + systemd-run --wait --pipe -p RestrictFileSystems="~proc" ls / + systemd-run --wait --pipe -p RestrictFileSystems="~@basic-api" ls / + (! systemd-run --wait --pipe -p RestrictFileSystems="~$ROOTFS" ls /) + (! systemd-run --wait --pipe -p RestrictFileSystems="~proc" ls /proc) + (! systemd-run --wait --pipe -p RestrictFileSystems="~@basic-api" ls /proc) + (! systemd-run --wait --pipe -p RestrictFileSystems="~proc foo @bar @basic-api" ls /proc) + (! systemd-run --wait --pipe -p RestrictFileSystems="~proc foo @bar @basic-api" ls /sys) + systemd-run --wait --pipe -p RestrictFileSystems="~proc devtmpfs sysfs" ls / + (! systemd-run --wait --pipe -p RestrictFileSystems="~proc devtmpfs sysfs" ls /proc) + (! systemd-run --wait --pipe -p RestrictFileSystems="~proc devtmpfs sysfs" ls /dev) + (! systemd-run --wait --pipe -p RestrictFileSystems="~proc devtmpfs sysfs" ls /sys) +fi + # Ensure that clean-up codepaths work correctly if activation ultimately fails touch /run/not-a-directory mkdir /tmp/root diff --git a/test/units/util.sh b/test/units/util.sh index fdfb91f8c6..b5ed73237c 100755 --- a/test/units/util.sh +++ b/test/units/util.sh @@ -197,3 +197,22 @@ openssl_supports_kdf() { # but let's do that when/if the need arises openssl kdf -keylen 16 -kdfopt digest:SHA2-256 -kdfopt key:foo -out /dev/null "$kdf" } + +kernel_supports_lsm() { + local lsm="${1:?}" + local items item + + if [[ ! -e /sys/kernel/security/lsm ]]; then + echo "/sys/kernel/security/lsm doesn't exist, assuming $lsm is not supported" + return 1 + fi + + mapfile -t -d, items