diff --git a/src/core/execute.c b/src/core/execute.c index acc59ef9db..d3266a9ab5 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/test/test-functions b/test/test-functions index f03a63ac04..dcb54ec243 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 @@ -633,11 +634,15 @@ EOF 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" @@ -656,11 +661,14 @@ 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" diff --git a/test/units/testsuite-29.sh b/test/units/testsuite-29.sh index 4dbb3a0752..1b927a8305 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' @@ -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 ff4f77def2..c79adba5e1 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 <