diff --git a/src/core/execute.c b/src/core/execute.c index acc59ef9db0..d3266a9ab53 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3373,7 +3373,7 @@ static int compile_symlinks( return r; } - if (!exec_directory_is_private(context, dt)) + if (!exec_directory_is_private(context, dt) || exec_context_with_rootfs(context)) continue; private_path = path_join(params->prefix[dt], "private", context->directories[dt].items[i].path); diff --git a/src/core/namespace.c b/src/core/namespace.c index f3c6b58f867..c8dc6c0503a 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1804,7 +1804,7 @@ static int apply_mounts( * exist, which means this will be a no-op. */ r = create_symlinks_from_tuples(root, exec_dir_symlinks); if (r < 0) - return r; + return log_debug_errno(r, "Failed to set up ExecDirectories symlinks inside mount namespace: %m"); /* Create a deny list we can pass to bind_mount_recursive() */ deny_list = new(char*, (*n_mounts)+1); diff --git a/test/test-functions b/test/test-functions index ba18a0ea2d5..dcb54ec2433 100644 --- a/test/test-functions +++ b/test/test-functions @@ -576,7 +576,8 @@ install_verity_minimal() { oldinitdir="$initdir" rm -rfv "$TESTDIR/minimal" export initdir="$TESTDIR/minimal" - mkdir -p "$initdir/usr/lib/systemd/system" "$initdir/usr/lib/extension-release.d" "$initdir/etc" "$initdir/var/tmp" "$initdir/opt" + # app0 will use TemporaryFileSystem=/var/lib, app1 will need the mount point in the base image + mkdir -p "$initdir/usr/lib/systemd/system" "$initdir/usr/lib/extension-release.d" "$initdir/etc" "$initdir/var/tmp" "$initdir/opt" "$initdir/var/lib/app1" setup_basic_dirs install_basic_tools # Shellcheck treats [[ -v VAR ]] as an assignment to avoid a different @@ -598,19 +599,23 @@ install_verity_minimal() { touch "$initdir/etc/machine-id" "$initdir/etc/resolv.conf" touch "$initdir/opt/some_file" echo MARKER=1 >>"$initdir/usr/lib/os-release" - echo "PORTABLE_PREFIXES=app0 minimal" >>"$initdir/usr/lib/os-release" - echo -e "[Service]\nExecStartPre=cat /usr/lib/os-release\nExecStart=sleep 120" >"$initdir/usr/lib/systemd/system/app0.service" - cp "$initdir/usr/lib/systemd/system/app0.service" "$initdir/usr/lib/systemd/system/app0-foo.service" + echo "PORTABLE_PREFIXES=app0 minimal minimal-app0" >>"$initdir/usr/lib/os-release" + cat >"$initdir/usr/lib/systemd/system/minimal-app0.service" <"$oldinitdir/usr/share/minimal_0.roothash" sed -i "s/MARKER=1/MARKER=2/g" "$initdir/usr/lib/os-release" - rm "$initdir/usr/lib/systemd/system/app0-foo.service" - cp "$initdir/usr/lib/systemd/system/app0.service" "$initdir/usr/lib/systemd/system/app0-bar.service" + rm "$initdir/usr/lib/systemd/system/minimal-app0-foo.service" + cp "$initdir/usr/lib/systemd/system/minimal-app0.service" "$initdir/usr/lib/systemd/system/minimal-app0-bar.service" - mksquashfs "$initdir" "$oldinitdir/usr/share/minimal_1.raw" + mksquashfs "$initdir" "$oldinitdir/usr/share/minimal_1.raw" -noappend veritysetup format "$oldinitdir/usr/share/minimal_1.raw" "$oldinitdir/usr/share/minimal_1.verity" | \ grep '^Root hash:' | cut -f2 | tr -d '\n' >"$oldinitdir/usr/share/minimal_1.roothash" @@ -629,16 +634,20 @@ install_verity_minimal() { Type=oneshot RemainAfterExit=yes ExecStart=/opt/script0.sh +TemporaryFileSystem=/var/lib +StateDirectory=app0 +RuntimeDirectory=app0 EOF cat >"$initdir/opt/script0.sh" < \${STATE_DIRECTORY}/foo cat /usr/lib/extension-release.d/extension-release.app0 EOF chmod +x "$initdir/opt/script0.sh" echo MARKER=1 >"$initdir/usr/lib/systemd/system/some_file" - mksquashfs "$initdir" "$oldinitdir/usr/share/app0.raw" + mksquashfs "$initdir" "$oldinitdir/usr/share/app0.raw" -noappend export initdir="$TESTDIR/app1" mkdir -p "$initdir/usr/lib/extension-release.d" "$initdir/usr/lib/systemd/system" "$initdir/opt" @@ -652,16 +661,19 @@ EOF Type=oneshot RemainAfterExit=yes ExecStart=/opt/script1.sh +StateDirectory=app1 +RuntimeDirectory=app1 EOF cat >"$initdir/opt/script1.sh" < \${STATE_DIRECTORY}/foo cat /usr/lib/extension-release.d/extension-release.app2 EOF chmod +x "$initdir/opt/script1.sh" echo MARKER=1 >"$initdir/usr/lib/systemd/system/other_file" - mksquashfs "$initdir" "$oldinitdir/usr/share/app1.raw" + mksquashfs "$initdir" "$oldinitdir/usr/share/app1.raw" -noappend ) } diff --git a/test/units/testsuite-29.sh b/test/units/testsuite-29.sh index fdb84b6b457..1b927a83052 100755 --- a/test/units/testsuite-29.sh +++ b/test/units/testsuite-29.sh @@ -6,10 +6,13 @@ set -eux set -o pipefail ARGS=() +state_directory=/var/lib/private/ if [[ -v ASAN_OPTIONS || -v UBSAN_OPTIONS ]]; then # If we're running under sanitizers, we need to use a less restrictive # profile, otherwise LSan syscall would get blocked by seccomp ARGS+=(--profile=trusted) + # With the trusted profile DynamicUser is disabled, so the storage is not in private/ + state_directory=/var/lib/ fi systemd-dissect --no-pager /usr/share/minimal_0.raw | grep -q '✓ portable service' @@ -24,29 +27,29 @@ cat </run/systemd/system/systemd-portabled.service.d/override.conf Environment=SYSTEMD_LOG_LEVEL=debug EOF -portablectl "${ARGS[@]}" attach --now --runtime /usr/share/minimal_0.raw app0 +portablectl "${ARGS[@]}" attach --now --runtime /usr/share/minimal_0.raw minimal-app0 -systemctl is-active app0.service -systemctl is-active app0-foo.service +systemctl is-active minimal-app0.service +systemctl is-active minimal-app0-foo.service set +o pipefail set +e -systemctl is-active app0-bar.service && exit 1 +systemctl is-active minimal-app0-bar.service && exit 1 set -e set -o pipefail -portablectl "${ARGS[@]}" reattach --now --runtime /usr/share/minimal_1.raw app0 +portablectl "${ARGS[@]}" reattach --now --runtime /usr/share/minimal_1.raw minimal-app0 -systemctl is-active app0.service -systemctl is-active app0-bar.service +systemctl is-active minimal-app0.service +systemctl is-active minimal-app0-bar.service set +o pipefail set +e -systemctl is-active app0-foo.service && exit 1 +systemctl is-active minimal-app0-foo.service && exit 1 set -e set -o pipefail portablectl list | grep -q -F "minimal_1" -portablectl detach --now --runtime /usr/share/minimal_1.raw app0 +portablectl detach --now --runtime /usr/share/minimal_1.raw minimal-app0 portablectl list | grep -q -F "No images." @@ -55,29 +58,29 @@ portablectl list | grep -q -F "No images." unsquashfs -dest /tmp/minimal_0 /usr/share/minimal_0.raw unsquashfs -dest /tmp/minimal_1 /usr/share/minimal_1.raw -portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/minimal_0 app0 +portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime /tmp/minimal_0 minimal-app0 -systemctl is-active app0.service -systemctl is-active app0-foo.service +systemctl is-active minimal-app0.service +systemctl is-active minimal-app0-foo.service set +o pipefail set +e -systemctl is-active app0-bar.service && exit 1 +systemctl is-active minimal-app0-bar.service && exit 1 set -e set -o pipefail -portablectl "${ARGS[@]}" reattach --now --enable --runtime /tmp/minimal_1 app0 +portablectl "${ARGS[@]}" reattach --now --enable --runtime /tmp/minimal_1 minimal-app0 -systemctl is-active app0.service -systemctl is-active app0-bar.service +systemctl is-active minimal-app0.service +systemctl is-active minimal-app0-bar.service set +o pipefail set +e -systemctl is-active app0-foo.service && exit 1 +systemctl is-active minimal-app0-foo.service && exit 1 set -e set -o pipefail portablectl list | grep -q -F "minimal_1" -portablectl detach --now --enable --runtime /tmp/minimal_1 app0 +portablectl detach --now --enable --runtime /tmp/minimal_1 minimal-app0 portablectl list | grep -q -F "No images." @@ -109,6 +112,12 @@ status="$(portablectl is-attached --extension app1 minimal_1)" portablectl detach --now --runtime --extension /usr/share/app1.raw /usr/share/minimal_1.raw app1 +# Ensure that the combination of read-only images, state directory and dynamic user works, and that +# state is retained. Check after detaching, as on slow systems (eg: sanitizers) it might take a while +# after the service is attached before the file appears. +grep -q -F bar "${state_directory}/app0/foo" +grep -q -F baz "${state_directory}/app1/foo" + # portablectl also works with directory paths rather than images mkdir /tmp/rootdir /tmp/app0 /tmp/app1 /tmp/overlay /tmp/os-release-fix /tmp/os-release-fix/etc diff --git a/test/units/testsuite-50.sh b/test/units/testsuite-50.sh index 7ddb20601a8..6aabbd139c3 100755 --- a/test/units/testsuite-50.sh +++ b/test/units/testsuite-50.sh @@ -308,7 +308,8 @@ systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.r cat >/run/systemd/system/testservice-50e.service <