blob: d15b675e2650cf366a0752ef1ac204d87b63bf85 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail
systemd-analyze log-level debug
test_directory() {
local directory="$1"
local path="$2"
# cleanup for previous invocation
for i in xxx xxx2 yyy zzz x:yz x:yz2; do
rm -rf "${path:?}/${i}" "${path:?}/private/${i}"
done
# Set everything up without DynamicUser=1
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
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
(! systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz test -f "${path}"/zzz/test-missing)
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
# Convert to DynamicUser=1
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
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"
systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}"=zzz:xxx -p TemporaryFileSystem="${path}":ro test -f "${path}"/xxx/test
(! systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=1 -p "${directory}"=zzz test -f "${path}"/zzz/test-missing)
test -L "${path}"/zzz
test -d "${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 # previous symlink is not removed
test ! -e "${path}"/private/yyy
test -f "${path}"/zzz/test
test ! -e "${path}"/zzz/test-missing
# Convert back
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
(! systemd-run --wait -p RuntimeDirectoryPreserve=yes -p DynamicUser=0 -p "${directory}"=zzz test -f "${path}"/zzz/test-missing)
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
# Exercise the unit parsing paths too
cat >/run/systemd/system/testservice-34.service <<EOF
[Service]
Type=oneshot
TemporaryFileSystem=${path}
RuntimeDirectoryPreserve=yes
${directory}=zzz:x\:yz zzz:x\:yz2
ExecStart=test -f ${path}/x:yz2/test
ExecStart=test -f ${path}/x:yz/test
ExecStart=test -f ${path}/zzz/test
EOF
systemctl daemon-reload
systemctl start --wait testservice-34.service
test -d "${path}"/zzz
test ! -L "${path}"/zzz
test ! -e "${path}"/private/zzz
test ! -L "${path}"/x:yz
test ! -L "${path}"/x:yz2
}
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
cat >/run/systemd/system/testservice-34-check-writable.service <<\EOF
[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; \
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 \) \
-prune -o -type d -writable -print 2>/dev/null | sort -u); \
[[ "$${#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" ]]; \
'
EOF
systemctl daemon-reload
systemctl start testservice-34-check-writable.service
}
test_directory "StateDirectory" "/var/lib"
test_directory "RuntimeDirectory" "/run"
test_directory "CacheDirectory" "/var/cache"
test_directory "LogsDirectory" "/var/log"
test_check_writable
systemd-analyze log-level info
touch /testok
|