2020-03-04 12:35:06 +03:00
#!/usr/bin/env bash
2021-10-17 19:13:06 +03:00
# SPDX-License-Identifier: LGPL-2.1-or-later
2021-04-09 20:39:41 +03:00
set -eux
2019-06-25 11:40:16 +03:00
set -o pipefail
systemd-analyze log-level debug
2022-09-22 07:08:32 +03:00
test_directory( ) {
2021-07-14 20:22:21 +03:00
local directory = " $1 "
local path = " $2 "
2019-06-25 11:40:16 +03:00
2022-09-22 07:08:32 +03:00
# cleanup for previous invocation
for i in xxx xxx2 yyy zzz x:yz x:yz2; do
rm -rf " ${ path : ? } / ${ i } " " ${ path : ? } /private/ ${ i } "
done
2021-07-14 20:22:21 +03:00
# Set everything up without DynamicUser=1
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz touch " ${ path } " /zzz/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz test -f " ${ path } " /zzz/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz -p TemporaryFileSystem = " ${ path } " test -f " ${ path } " /zzz/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz:yyy test -f " ${ path } " /yyy/test
2022-09-22 07:08:32 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } =zzz:xxx zzz:xxx2 " -p TemporaryFileSystem = " ${ path } " bash -c " test -f ${ path } /xxx/test && test -f ${ path } /xxx2/test "
2021-07-14 20:22:21 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz:xxx -p TemporaryFileSystem = " ${ path } " :ro test -f " ${ path } " /xxx/test
2023-04-05 16:50:42 +03:00
( ! systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz test -f " ${ path } " /zzz/test-missing)
2024-10-28 22:58:58 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = "www::ro www:ro:ro" test -d " ${ path } " /www
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = "www::ro www:ro:ro" test -L " ${ path } " /ro
( ! systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = "www::ro www:ro:ro" sh -c " echo foo > ${ path } /www/test-missing " )
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
test -d " ${ path } " /zzz
test ! -L " ${ path } " /zzz
test ! -e " ${ path } " /private/zzz
2022-09-22 07:08:32 +03:00
test ! -e " ${ path } " /xxx
test ! -e " ${ path } " /private/xxx
test ! -e " ${ path } " /xxx2
test ! -e " ${ path } " /private/xxx2
test -L " ${ path } " /yyy
test ! -e " ${ path } " /private/yyy
2021-07-14 20:22:21 +03:00
test -f " ${ path } " /zzz/test
2022-09-22 07:08:32 +03:00
test ! -e " ${ path } " /zzz/test-missing
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
# Convert to DynamicUser=1
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = zzz test -f " ${ path } " /zzz/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = zzz -p TemporaryFileSystem = " ${ path } " test -f " ${ path } " /zzz/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = zzz:yyy test -f " ${ path } " /yyy/test
2022-09-22 07:08:32 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } =zzz:xxx zzz:xxx2 " \
-p TemporaryFileSystem = " ${ path } " -p EnvironmentFile = -/usr/lib/systemd/systemd-asan-env bash -c " test -f ${ path } /xxx/test && test -f ${ path } /xxx2/test "
2021-07-14 20:22:21 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = zzz:xxx -p TemporaryFileSystem = " ${ path } " :ro test -f " ${ path } " /xxx/test
2023-04-05 16:50:42 +03:00
( ! systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = zzz test -f " ${ path } " /zzz/test-missing)
2024-10-28 22:58:58 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = "www::ro www:ro:ro" test -d " ${ path } " /www
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = "www::ro www:ro:ro" test -L " ${ path } " /ro
( ! systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 1 -p " ${ directory } " = "www::ro www:ro:ro" sh -c " echo foo > ${ path } /www/test-missing " )
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
test -L " ${ path } " /zzz
test -d " ${ path } " /private/zzz
2022-09-22 07:08:32 +03:00
test ! -e " ${ path } " /xxx
test ! -e " ${ path } " /private/xxx
test ! -e " ${ path } " /xxx2
test ! -e " ${ path } " /private/xxx2
test -L " ${ path } " /yyy # previous symlink is not removed
test ! -e " ${ path } " /private/yyy
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
test -f " ${ path } " /zzz/test
2022-09-22 07:08:32 +03:00
test ! -e " ${ path } " /zzz/test-missing
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
# Convert back
2019-06-25 11:40:16 +03:00
2021-07-14 20:22:21 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz test -f " ${ path } " /zzz/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz -p TemporaryFileSystem = " ${ path } " test -f " ${ path } " /zzz/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz:yyy test -f " ${ path } " /yyy/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz:xxx -p TemporaryFileSystem = " ${ path } " test -f " ${ path } " /xxx/test
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } =zzz:xxx zzz:xxx2 " -p TemporaryFileSystem = " ${ path } " bash -c " test -f ${ path } /xxx/test && test -f ${ path } /xxx2/test "
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz:xxx -p TemporaryFileSystem = " ${ path } " :ro test -f " ${ path } " /xxx/test
2023-04-05 16:50:42 +03:00
( ! systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = zzz test -f " ${ path } " /zzz/test-missing)
2024-10-28 22:58:58 +03:00
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = "www::ro www:ro:ro" test -d " ${ path } " /www
systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = "www::ro www:ro:ro" test -L " ${ path } " /ro
( ! systemd-run --wait -p RuntimeDirectoryPreserve = yes -p DynamicUser = 0 -p " ${ directory } " = "www::ro www:ro:ro" sh -c " echo foo > ${ path } /www/test-missing " )
2021-07-14 20:22:21 +03:00
2022-09-22 07:08:32 +03:00
test -d " ${ path } " /zzz
test ! -L " ${ path } " /zzz
test ! -e " ${ path } " /private/zzz
test ! -e " ${ path } " /xxx
test ! -e " ${ path } " /private/xxx
test ! -e " ${ path } " /xxx2
test ! -e " ${ path } " /private/xxx2
test -L " ${ path } " /yyy
test ! -e " ${ path } " /private/yyy
test -f " ${ path } " /zzz/test
test ! -e " ${ path } " /zzz/test-missing
2024-10-28 22:58:58 +03:00
test -d " ${ path } " /www
test ! -e " ${ path } " /www/test-missing
2022-09-22 07:08:32 +03:00
2021-07-14 20:22:21 +03:00
# Exercise the unit parsing paths too
cat >/run/systemd/system/testservice-34.service <<EOF
[ Service]
Type = oneshot
TemporaryFileSystem = ${ path }
RuntimeDirectoryPreserve = yes
2024-10-28 22:58:58 +03:00
${ directory } = zzz:x\: yz zzz:x\: yz2 www::ro www:ro:ro
2021-07-14 20:22:21 +03:00
ExecStart = test -f ${ path } /x:yz2/test
ExecStart = test -f ${ path } /x:yz/test
ExecStart = test -f ${ path } /zzz/test
2024-10-28 22:58:58 +03:00
ExecStart = test -d ${ path } /www
ExecStart = test -L ${ path } /ro
ExecStart = sh -c " ! test -w ${ path } /www "
2021-07-14 20:22:21 +03:00
EOF
systemctl daemon-reload
systemctl start --wait testservice-34.service
test -d " ${ path } " /zzz
test ! -L " ${ path } " /zzz
test ! -e " ${ path } " /private/zzz
2022-09-22 07:08:32 +03:00
2021-07-14 20:22:21 +03:00
test ! -L " ${ path } " /x:yz
test ! -L " ${ path } " /x:yz2
}
2022-09-22 07:08:32 +03:00
test_check_writable( ) {
# cleanup for previous invocation
for i in aaa quux waldo xxx; do
rm -rf " /var/lib/ $i " " /var/lib/private/ $i "
done
2022-10-17 15:38:00 +03:00
cat >/run/systemd/system/testservice-34-check-writable.service <<\E OF
2022-09-22 07:08:32 +03:00
[ Unit]
Description = Check writable directories when DynamicUser = with StateDirectory =
[ Service]
# Relevant only for sanitizer runs
EnvironmentFile = -/usr/lib/systemd/systemd-asan-env
Type = oneshot
DynamicUser = yes
StateDirectory = waldo quux/pief aaa/bbb aaa aaa/ccc xxx/yyy:aaa/111 xxx:aaa/222 xxx/zzz:aaa/333
# Make sure that the state directories are really the only writable directory besides the obvious candidates
ExecStart = bash -c ' \
set -eux; \
set -o pipefail; \
declare -a writable_dirs; \
2022-10-17 15:38:00 +03:00
readarray -t writable_dirs < <( find / \( -path /var/tmp -o -path /tmp -o -path /proc -o -path /dev/mqueue -o -path /dev/shm -o \
-path /sys/fs/bpf -o -path /dev/.lxc -o -path /sys/devices/system/cpu \) \
2022-09-22 07:08:32 +03:00
-prune -o -type d -writable -print 2>/dev/null | sort -u) ; \
2022-10-17 15:38:00 +03:00
[ [ " $$ {#writable_dirs[@]} " = = "8" ] ] ; \
[ [ " $$ {writable_dirs[0]} " = = "/var/lib/private/aaa" ] ] ; \
[ [ " $$ {writable_dirs[1]} " = = "/var/lib/private/aaa/bbb" ] ] ; \
[ [ " $$ {writable_dirs[2]} " = = "/var/lib/private/aaa/ccc" ] ] ; \
[ [ " $$ {writable_dirs[3]} " = = "/var/lib/private/quux/pief" ] ] ; \
[ [ " $$ {writable_dirs[4]} " = = "/var/lib/private/waldo" ] ] ; \
[ [ " $$ {writable_dirs[5]} " = = "/var/lib/private/xxx" ] ] ; \
[ [ " $$ {writable_dirs[6]} " = = "/var/lib/private/xxx/yyy" ] ] ; \
[ [ " $$ {writable_dirs[7]} " = = "/var/lib/private/xxx/zzz" ] ] ; \
2022-09-22 07:08:32 +03:00
'
EOF
systemctl daemon-reload
systemctl start testservice-34-check-writable.service
}
2024-08-06 02:43:29 +03:00
test_check_idmapped_mounts( ) {
rm -rf /var/lib/testidmapped /var/lib/private/testidmapped
cat >/run/systemd/system/testservice-34-check-idmapped.service <<\E OF
[ Unit]
Description = Check id-mapped directories when DynamicUser = yes with StateDirectory
[ Service]
# Relevant only for sanitizer runs
EnvironmentFile = -/usr/lib/systemd/systemd-asan-env
Type = oneshot
MountAPIVFS = yes
DynamicUser = yes
PrivateUsers = yes
TemporaryFileSystem = /run /var/opt /var/lib /vol
UMask = 0000
StateDirectory = testidmapped:sampleservice
ExecStart = /bin/bash -c ' \
set -eux; \
set -o pipefail; \
touch /var/lib/sampleservice/testfile; \
[ [ $( awk "NR==2 {print \$1}" /proc/self/uid_map) = = $( stat -c "%%u" /var/lib/private/testidmapped/testfile) ] ] ; \
'
EOF
systemctl daemon-reload
systemctl start testservice-34-check-idmapped.service
[ [ $( stat -c "%u" /var/lib/private/testidmapped/testfile) = = 65534 ] ]
}
test_check_idmapped_mounts_root( ) {
rm -rf /var/lib/testidmapped /var/lib/private/testidmapped
cat >/run/systemd/system/testservice-34-check-idmapped.service <<\E OF
[ Unit]
Description = Check id-mapped directories when DynamicUser = no with StateDirectory
[ Service]
# Relevant only for sanitizer runs
EnvironmentFile = -/usr/lib/systemd/systemd-asan-env
Type = oneshot
MountAPIVFS = yes
User = root
DynamicUser = no
PrivateUsers = no
TemporaryFileSystem = /run /var/opt /var/lib /vol
UMask = 0000
StateDirectory = testidmapped:sampleservice
ExecStart = /bin/bash -c ' \
set -eux; \
set -o pipefail; \
touch /var/lib/sampleservice/testfile; \
[ [ 0 = = $( stat -c "%%u" /var/lib/testidmapped/testfile) ] ] ; \
'
EOF
systemctl daemon-reload
systemctl start testservice-34-check-idmapped.service
[ [ $( stat -c "%u" /var/lib/testidmapped/testfile) = = 0 ] ]
}
2021-07-14 20:22:21 +03:00
test_directory "StateDirectory" "/var/lib"
test_directory "RuntimeDirectory" "/run"
test_directory "CacheDirectory" "/var/cache"
test_directory "LogsDirectory" "/var/log"
2019-06-25 11:40:16 +03:00
2022-09-22 07:08:32 +03:00
test_check_writable
2024-08-06 02:43:29 +03:00
if systemd-analyze compare-versions " $( uname -r) " ge 5.12; then
test_check_idmapped_mounts
test_check_idmapped_mounts_root
fi
2019-06-25 11:40:16 +03:00
systemd-analyze log-level info
2023-07-12 16:49:55 +03:00
touch /testok