core: do not attempt to add 'private' symlinks when RootImage/RootDirectory are used

A bind mount is added directly from private on the host to the actual
destination directory, no need for the symlinks (which cannot be created
as the bind mount happens first and creates the target as an actual directory)

Fixes https://github.com/systemd/systemd/issues/22264
This commit is contained in:
Luca Boccassi 2022-01-27 14:10:34 +00:00
parent 6d7c999ab5
commit 3fa80e5e75
4 changed files with 23 additions and 4 deletions

View file

@ -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);

View file

@ -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" <<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"
@ -656,11 +661,14 @@ EOF
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"

View file

@ -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

View file

@ -308,7 +308,8 @@ systemd-run -P --property ExtensionImages="/usr/share/app0.raw /usr/share/app1.r
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
@ -336,7 +337,8 @@ systemd-run -P --property ExtensionDirectories="${image_dir}/app0 ${image_dir}/a
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