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);
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
Type=oneshot
RemainAfterExit=yes
ExecStart=/opt/script0.sh
+TemporaryFileSystem=/var/lib
+StateDirectory=app0
+RuntimeDirectory=app0
EOF
cat >"$initdir/opt/script0.sh" <<EOF
#!/bin/bash
set -e
test -e /usr/lib/os-release
+echo bar > \${STATE_DIRECTORY}/foo
cat /usr/lib/extension-release.d/extension-release.app0
EOF
chmod +x "$initdir/opt/script0.sh"
Type=oneshot
RemainAfterExit=yes
ExecStart=/opt/script1.sh
+StateDirectory=app1
+RuntimeDirectory=app1
EOF
cat >"$initdir/opt/script1.sh" <<EOF
#!/bin/bash
set -e
test -e /usr/lib/os-release
+echo baz > \${STATE_DIRECTORY}/foo
cat /usr/lib/extension-release.d/extension-release.app2
EOF
chmod +x "$initdir/opt/script1.sh"
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'
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
cat >/run/systemd/system/testservice-50e.service <<EOF
[Service]
MountAPIVFS=yes
-TemporaryFileSystem=/run
+TemporaryFileSystem=/run /var/lib
+StateDirectory=app0
RootImage=${image}.raw
ExtensionImages=/usr/share/app0.raw /usr/share/app1.raw:nosuid
# Relevant only for sanitizer runs
cat >/run/systemd/system/testservice-50f.service <<EOF
[Service]
MountAPIVFS=yes
-TemporaryFileSystem=/run
+TemporaryFileSystem=/run /var/lib
+StateDirectory=app0
RootImage=${image}.raw
ExtensionDirectories=${image_dir}/app0 ${image_dir}/app1
# Relevant only for sanitizer runs