]>
Commit | Line | Data |
---|---|---|
4b622119 | 1 | #!/usr/bin/env bash |
7b3cec95 | 2 | # SPDX-License-Identifier: LGPL-2.1-or-later |
4b622119 MG |
3 | # shellcheck disable=SC2016 |
4 | set -eux | |
5 | ||
cb153b4f FS |
6 | # shellcheck source=test/units/util.sh |
7 | . "$(dirname "$0")"/util.sh | |
cf906bea | 8 | |
926d95cd | 9 | systemctl log-level debug |
cb942444 | 10 | export SYSTEMD_LOG_LEVEL=debug |
4b622119 | 11 | |
6c83054c FS |
12 | # Sanity checks |
13 | # | |
15381369 | 14 | # We can't really test time, critical-chain and plot verbs here, as |
6c83054c FS |
15 | # the testsuite service is a part of the boot transaction, so let's assume |
16 | # they fail | |
17 | systemd-analyze || : | |
18 | systemd-analyze time || : | |
6c83054c | 19 | systemd-analyze critical-chain || : |
15381369 YW |
20 | # blame |
21 | systemd-analyze blame | |
22 | systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame | |
cbe884f1 | 23 | (! systemd-analyze blame --global) |
a23be57d | 24 | # plot |
6c83054c | 25 | systemd-analyze plot >/dev/null || : |
a23be57d | 26 | systemd-analyze plot --json=pretty >/dev/null || : |
27 | systemd-analyze plot --json=short >/dev/null || : | |
28 | systemd-analyze plot --json=off >/dev/null || : | |
29 | systemd-analyze plot --json=pretty --no-legend >/dev/null || : | |
30 | systemd-analyze plot --json=short --no-legend >/dev/null || : | |
31 | systemd-analyze plot --json=off --no-legend >/dev/null || : | |
32 | systemd-analyze plot --table >/dev/null || : | |
33 | systemd-analyze plot --table --no-legend >/dev/null || : | |
cbe884f1 | 34 | (! systemd-analyze plot --global) |
926d95cd FS |
35 | # legacy/deprecated options (moved to systemctl, but still usable from analyze) |
36 | systemd-analyze log-level | |
37 | systemd-analyze log-level "$(systemctl log-level)" | |
38 | systemd-analyze get-log-level | |
39 | systemd-analyze set-log-level "$(systemctl log-level)" | |
40 | systemd-analyze log-target | |
41 | systemd-analyze log-target "$(systemctl log-target)" | |
42 | systemd-analyze get-log-target | |
43 | systemd-analyze set-log-target "$(systemctl log-target)" | |
44 | systemd-analyze service-watchdogs | |
45 | systemd-analyze service-watchdogs "$(systemctl service-watchdogs)" | |
6c83054c FS |
46 | # dot |
47 | systemd-analyze dot >/dev/null | |
48 | systemd-analyze dot systemd-journald.service >/dev/null | |
49 | systemd-analyze dot systemd-journald.service systemd-logind.service >/dev/null | |
50 | systemd-analyze dot --from-pattern="*" --from-pattern="*.service" systemd-journald.service >/dev/null | |
51 | systemd-analyze dot --to-pattern="*" --to-pattern="*.service" systemd-journald.service >/dev/null | |
52 | systemd-analyze dot --from-pattern="*.service" --to-pattern="*.service" systemd-journald.service >/dev/null | |
53 | systemd-analyze dot --order systemd-journald.service systemd-logind.service >/dev/null | |
54 | systemd-analyze dot --require systemd-journald.service systemd-logind.service >/dev/null | |
55 | systemd-analyze dot "systemd-*.service" >/dev/null | |
56 | (! systemd-analyze dot systemd-journald.service systemd-logind.service "*" bbb ccc) | |
cbe884f1 | 57 | (! systemd-analyze dot --global systemd-journald.service) |
6c83054c | 58 | # dump |
d9365956 LB |
59 | # this should be rate limited to 10 calls in 10 minutes for unprivileged callers |
60 | for _ in {1..10}; do | |
61 | runas testuser systemd-analyze dump systemd-journald.service >/dev/null | |
62 | done | |
63 | (! runas testuser systemd-analyze dump >/dev/null) | |
64 | # still limited after a reload | |
65 | systemctl daemon-reload | |
66 | (! runas testuser systemd-analyze dump >/dev/null) | |
67 | # and a re-exec | |
68 | systemctl daemon-reexec | |
69 | (! runas testuser systemd-analyze dump >/dev/null) | |
70 | # privileged call, so should not be rate limited | |
71 | for _ in {1..10}; do | |
72 | systemd-analyze dump systemd-journald.service >/dev/null | |
73 | done | |
6c83054c FS |
74 | systemd-analyze dump >/dev/null |
75 | systemd-analyze dump "*" >/dev/null | |
76 | systemd-analyze dump "*.socket" >/dev/null | |
8b1879bc | 77 | systemd-analyze dump "*.socket" "*.service" aaaaaaa ... >/dev/null |
6c83054c FS |
78 | systemd-analyze dump systemd-journald.service >/dev/null |
79 | (! systemd-analyze dump "") | |
cbe884f1 YW |
80 | (! systemd-analyze dump --global systemd-journald.service) |
81 | # malloc | |
82 | systemd-analyze malloc >/dev/null | |
83 | (! systemd-analyze malloc --global) | |
8b1879bc FS |
84 | # unit-files |
85 | systemd-analyze unit-files >/dev/null | |
86 | systemd-analyze unit-files systemd-journald.service >/dev/null | |
87 | systemd-analyze unit-files "*" >/dev/null | |
88 | systemd-analyze unit-files "*" aaaaaa "*.service" "*.target" >/dev/null | |
89 | systemd-analyze unit-files --user >/dev/null | |
90 | systemd-analyze unit-files --user "*" aaaaaa "*.service" "*.target" >/dev/null | |
cbe884f1 | 91 | (! systemd-analyze unit-files --global) |
6c83054c FS |
92 | # unit-paths |
93 | systemd-analyze unit-paths | |
94 | systemd-analyze unit-paths --user | |
95 | systemd-analyze unit-paths --global | |
96 | # exist-status | |
97 | systemd-analyze exit-status | |
98 | systemd-analyze exit-status STDOUT BPF | |
99 | systemd-analyze exit-status 0 1 {63..65} | |
100 | (! systemd-analyze exit-status STDOUT BPF "hello*") | |
cbe884f1 | 101 | (! systemd-analyze exit-status --global) |
6c83054c FS |
102 | # capability |
103 | systemd-analyze capability | |
104 | systemd-analyze capability cap_chown CAP_KILL | |
105 | systemd-analyze capability 0 1 {30..32} | |
106 | (! systemd-analyze capability cap_chown CAP_KILL "hello*") | |
cbe884f1 | 107 | (! systemd-analyze capability --global) |
6c83054c FS |
108 | # condition |
109 | mkdir -p /run/systemd/system | |
110 | UNIT_NAME="analyze-condition-$RANDOM.service" | |
111 | cat >"/run/systemd/system/$UNIT_NAME" <<EOF | |
112 | [Unit] | |
113 | AssertPathExists=/etc/os-release | |
114 | AssertEnvironment=!FOOBAR | |
115 | ConditionKernelVersion=>1.0 | |
116 | ConditionPathExists=/etc/os-release | |
117 | ||
118 | [Service] | |
63403f07 | 119 | ExecStart=true |
6c83054c FS |
120 | EOF |
121 | systemctl daemon-reload | |
122 | systemd-analyze condition --unit="$UNIT_NAME" | |
123 | systemd-analyze condition 'ConditionKernelVersion = ! <4.0' \ | |
124 | 'ConditionKernelVersion = >=3.1' \ | |
125 | 'ConditionACPower=|false' \ | |
126 | 'ConditionArchitecture=|!arm' \ | |
127 | 'AssertPathExists=/etc/os-release' | |
128 | (! systemd-analyze condition 'ConditionArchitecture=|!arm' 'AssertXYZ=foo') | |
129 | (! systemd-analyze condition 'ConditionKernelVersion=<1.0') | |
130 | (! systemd-analyze condition 'AssertKernelVersion=<1.0') | |
cbe884f1 | 131 | (! systemd-analyze condition --global 'ConditionKernelVersion = ! <4.0') |
6c83054c FS |
132 | # syscall-filter |
133 | systemd-analyze syscall-filter >/dev/null | |
134 | systemd-analyze syscall-filter @chown @sync | |
135 | systemd-analyze syscall-filter @sync @sync @sync | |
136 | (! systemd-analyze syscall-filter @chown @sync @foobar) | |
cbe884f1 | 137 | (! systemd-analyze syscall-filter --global) |
6c83054c FS |
138 | # filesystems (requires libbpf support) |
139 | if systemctl --version | grep "+BPF_FRAMEWORK"; then | |
140 | systemd-analyze filesystems >/dev/null | |
141 | systemd-analyze filesystems @basic-api | |
142 | systemd-analyze filesystems @basic-api @basic-api @basic-api | |
143 | (! systemd-analyze filesystems @basic-api @basic-api @foobar @basic-api) | |
cbe884f1 | 144 | (! systemd-analyze filesystems --global @basic-api) |
6c83054c FS |
145 | fi |
146 | # calendar | |
147 | systemd-analyze calendar '*-2-29 0:0:0' | |
148 | systemd-analyze calendar --iterations=5 '*-2-29 0:0:0' | |
149 | systemd-analyze calendar '*-* *:*:*' | |
150 | systemd-analyze calendar --iterations=5 '*-* *:*:*' | |
151 | systemd-analyze calendar --iterations=50 '*-* *:*:*' | |
152 | systemd-analyze calendar --iterations=0 '*-* *:*:*' | |
8b1879bc | 153 | systemd-analyze calendar --iterations=5 '01-01-22 01:00:00' |
6c83054c FS |
154 | systemd-analyze calendar --base-time=yesterday --iterations=5 '*-* *:*:*' |
155 | (! systemd-analyze calendar --iterations=0 '*-* 99:*:*') | |
156 | (! systemd-analyze calendar --base-time=never '*-* *:*:*') | |
157 | (! systemd-analyze calendar 1) | |
158 | (! systemd-analyze calendar "") | |
cbe884f1 | 159 | (! systemd-analyze calendar --global '*-2-29 0:0:0') |
6c83054c FS |
160 | # timestamp |
161 | systemd-analyze timestamp now | |
162 | systemd-analyze timestamp -- -1 | |
163 | systemd-analyze timestamp yesterday now tomorrow | |
164 | (! systemd-analyze timestamp yesterday never tomorrow) | |
165 | (! systemd-analyze timestamp 1) | |
8b1879bc | 166 | (! systemd-analyze timestamp '*-2-29 0:0:0') |
6c83054c | 167 | (! systemd-analyze timestamp "") |
cbe884f1 | 168 | (! systemd-analyze timestamp --global now) |
6c83054c FS |
169 | # timespan |
170 | systemd-analyze timespan 1 | |
171 | systemd-analyze timespan 1s 300s '1year 0.000001s' | |
172 | (! systemd-analyze timespan 1s 300s aaaaaa '1year 0.000001s') | |
173 | (! systemd-analyze timespan -- -1) | |
8b1879bc | 174 | (! systemd-analyze timespan '*-2-29 0:0:0') |
6c83054c | 175 | (! systemd-analyze timespan "") |
cbe884f1 | 176 | (! systemd-analyze timespan --global 1) |
6c83054c FS |
177 | # cat-config |
178 | systemd-analyze cat-config systemd/system.conf >/dev/null | |
179 | systemd-analyze cat-config /etc/systemd/system.conf >/dev/null | |
180 | systemd-analyze cat-config systemd/system.conf systemd/journald.conf >/dev/null | |
181 | systemd-analyze cat-config systemd/system.conf foo/bar systemd/journald.conf >/dev/null | |
182 | systemd-analyze cat-config foo/bar | |
063c8382 ZJS |
183 | systemd-analyze cat-config --tldr systemd/system.conf >/dev/null |
184 | systemd-analyze cat-config --tldr /etc/systemd/system.conf >/dev/null | |
185 | systemd-analyze cat-config --tldr systemd/system.conf systemd/journald.conf >/dev/null | |
186 | systemd-analyze cat-config --tldr systemd/system.conf foo/bar systemd/journald.conf >/dev/null | |
187 | systemd-analyze cat-config --tldr foo/bar | |
cbe884f1 | 188 | (! systemd-analyze cat-config --global systemd/system.conf) |
f7f5657e FS |
189 | # security |
190 | systemd-analyze security | |
191 | systemd-analyze security --json=off | |
192 | systemd-analyze security --json=pretty | jq | |
193 | systemd-analyze security --json=short | jq | |
cbe884f1 | 194 | (! systemd-analyze security --global) |
6c83054c | 195 | |
a7eed3ec ZJS |
196 | if [[ ! -v ASAN_OPTIONS ]]; then |
197 | # check that systemd-analyze cat-config paths work in a chroot | |
198 | mkdir -p /tmp/root | |
5183976c YW |
199 | mount --bind / /tmp/root |
200 | if mountpoint -q /usr; then | |
201 | mount --bind /usr /tmp/root/usr | |
202 | fi | |
a7eed3ec ZJS |
203 | systemd-analyze cat-config systemd/system-preset >/tmp/out1 |
204 | chroot /tmp/root systemd-analyze cat-config systemd/system-preset >/tmp/out2 | |
205 | diff /tmp/out{1,2} | |
206 | fi | |
207 | ||
208 | # verify | |
4b622119 MG |
209 | mkdir -p /tmp/img/usr/lib/systemd/system/ |
210 | mkdir -p /tmp/img/opt/ | |
211 | ||
212 | touch /tmp/img/opt/script0.sh | |
213 | chmod +x /tmp/img/opt/script0.sh | |
214 | ||
215 | cat <<EOF >/tmp/img/usr/lib/systemd/system/testfile.service | |
216 | [Service] | |
217 | ExecStart = /opt/script0.sh | |
218 | EOF | |
219 | ||
220 | set +e | |
221 | # Default behaviour is to recurse through all dependencies when unit is loaded | |
128db0aa | 222 | (! systemd-analyze verify --root=/tmp/img/ testfile.service) |
4b622119 MG |
223 | |
224 | # As above, recurses through all dependencies when unit is loaded | |
128db0aa | 225 | (! systemd-analyze verify --recursive-errors=yes --root=/tmp/img/ testfile.service) |
4b622119 MG |
226 | |
227 | # Recurses through unit file and its direct dependencies when unit is loaded | |
128db0aa | 228 | (! systemd-analyze verify --recursive-errors=one --root=/tmp/img/ testfile.service) |
4b622119 MG |
229 | |
230 | set -e | |
231 | ||
232 | # zero exit status since dependencies are ignored when unit is loaded | |
233 | systemd-analyze verify --recursive-errors=no --root=/tmp/img/ testfile.service | |
234 | ||
235 | rm /tmp/img/usr/lib/systemd/system/testfile.service | |
236 | ||
237 | cat <<EOF >/tmp/testfile.service | |
238 | [Unit] | |
239 | foo = bar | |
240 | ||
241 | [Service] | |
242 | ExecStart = echo hello | |
243 | EOF | |
244 | ||
245 | cat <<EOF >/tmp/testfile2.service | |
246 | [Unit] | |
247 | Requires = testfile.service | |
248 | ||
249 | [Service] | |
250 | ExecStart = echo hello | |
251 | EOF | |
252 | ||
253 | # Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded | |
254 | systemd-analyze verify --recursive-errors=no /tmp/testfile2.service | |
255 | ||
256 | set +e | |
ba669952 | 257 | # Non-zero exit status since all associated dependencies are recursively loaded when the unit file is loaded |
128db0aa | 258 | (! systemd-analyze verify --recursive-errors=yes /tmp/testfile2.service) |
4b622119 MG |
259 | set -e |
260 | ||
261 | rm /tmp/testfile.service | |
262 | rm /tmp/testfile2.service | |
263 | ||
f660c7fa MG |
264 | cat <<EOF >/tmp/sample.service |
265 | [Unit] | |
266 | Description = A Sample Service | |
267 | ||
268 | [Service] | |
269 | ExecStart = echo hello | |
270 | Slice=support.slice | |
271 | EOF | |
272 | ||
273 | # Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded | |
274 | systemd-analyze verify --recursive-errors=no /tmp/sample.service | |
275 | ||
4b622119 MG |
276 | cat <<EOF >/tmp/testfile.service |
277 | [Service] | |
278 | ExecStart = echo hello | |
6a59dfa1 | 279 | DeviceAllow=/dev/sda |
4b622119 MG |
280 | EOF |
281 | ||
14bb7295 AZ |
282 | # Prevent regression from #13380 and #20859 where we can't verify hidden files |
283 | cp /tmp/testfile.service /tmp/.testfile.service | |
284 | ||
285 | systemd-analyze verify /tmp/.testfile.service | |
286 | ||
287 | rm /tmp/.testfile.service | |
4b622119 | 288 | |
da845dab AB |
289 | # Alias a unit file's name on disk (see #20061) |
290 | cp /tmp/testfile.service /tmp/testsrvc | |
291 | ||
128db0aa | 292 | (! systemd-analyze verify /tmp/testsrvc) |
da845dab AB |
293 | |
294 | systemd-analyze verify /tmp/testsrvc:alias.service | |
295 | ||
4b622119 MG |
296 | # Zero exit status since the value used for comparison determine exposure to security threats is by default 100 |
297 | systemd-analyze security --offline=true /tmp/testfile.service | |
298 | ||
4b622119 | 299 | #The overall exposure level assigned to the unit is greater than the set threshold |
128db0aa | 300 | (! systemd-analyze security --threshold=90 --offline=true /tmp/testfile.service) |
4b622119 | 301 | |
6a59dfa1 LB |
302 | # Ensure we print the list of ACLs, see https://github.com/systemd/systemd/issues/23185 |
303 | systemd-analyze security --offline=true /tmp/testfile.service | grep -q -F "/dev/sda" | |
304 | ||
452f91d8 | 305 | # Make sure that running generators under systemd-analyze verify works. |
95400d1d FS |
306 | # Note: sd-analyze spawns generators in a sandbox which makes gcov unhapy, so temporarily override |
307 | # $GCOV_PREFIX to make it skip generating any coverage reports | |
308 | GCOV_PREFIX=/tmp systemd-analyze verify --generators /tmp/testfile.service | |
452f91d8 | 309 | |
4b622119 MG |
310 | rm /tmp/testfile.service |
311 | ||
312 | cat <<EOF >/tmp/img/usr/lib/systemd/system/testfile.service | |
313 | [Service] | |
314 | ExecStart = echo hello | |
315 | PrivateNetwork = yes | |
316 | PrivateDevices = yes | |
317 | PrivateUsers = yes | |
318 | EOF | |
319 | ||
320 | # The new overall exposure level assigned to the unit is less than the set thresholds | |
321 | # Verifies that the --offline= option works with --root= | |
322 | systemd-analyze security --threshold=90 --offline=true --root=/tmp/img/ testfile.service | |
323 | ||
9d51ab78 YW |
324 | cat <<EOF >/tmp/foo@.service |
325 | [Service] | |
326 | ExecStart=ls | |
327 | EOF | |
328 | ||
329 | cat <<EOF >/tmp/hoge@test.service | |
330 | [Service] | |
331 | ExecStart=ls | |
332 | EOF | |
333 | ||
334 | # issue #30357 | |
335 | pushd /tmp | |
336 | systemd-analyze verify foo@bar.service | |
337 | systemd-analyze verify foo@.service | |
338 | systemd-analyze verify hoge@test.service | |
339 | (! systemd-analyze verify hoge@nonexist.service) | |
340 | (! systemd-analyze verify hoge@.service) | |
341 | popd | |
342 | pushd / | |
343 | systemd-analyze verify tmp/foo@bar.service | |
344 | systemd-analyze verify tmp/foo@.service | |
345 | systemd-analyze verify tmp/hoge@test.service | |
346 | (! systemd-analyze verify tmp/hoge@nonexist.service) | |
347 | (! systemd-analyze verify tmp/hoge@.service) | |
348 | popd | |
349 | pushd /usr | |
350 | systemd-analyze verify ../tmp/foo@bar.service | |
351 | systemd-analyze verify ../tmp/foo@.service | |
352 | systemd-analyze verify ../tmp/hoge@test.service | |
353 | (! systemd-analyze verify ../tmp/hoge@nonexist.service) | |
354 | (! systemd-analyze verify ../tmp/hoge@.service) | |
355 | popd | |
356 | systemd-analyze verify /tmp/foo@bar.service | |
357 | systemd-analyze verify /tmp/foo@.service | |
358 | systemd-analyze verify /tmp/hoge@test.service | |
359 | (! systemd-analyze verify /tmp/hoge@nonexist.service) | |
360 | (! systemd-analyze verify /tmp/hoge@.service) | |
361 | ||
abf0ccc1 YW |
362 | # test that all commands are verified. |
363 | cat <<EOF >/tmp/multi-exec-start.service | |
364 | [Service] | |
365 | Type=oneshot | |
366 | ExecStart=true | |
367 | ExecStart=ls | |
368 | EOF | |
369 | systemd-analyze verify /tmp/multi-exec-start.service | |
370 | echo 'ExecStart=command-should-not-exist' >>/tmp/multi-exec-start.service | |
371 | (! systemd-analyze verify /tmp/multi-exec-start.service) | |
372 | ||
4b622119 MG |
373 | # Added an additional "INVALID_ID" id to the .json to verify that nothing breaks when input is malformed |
374 | # The PrivateNetwork id description and weight was changed to verify that 'security' is actually reading in | |
375 | # values from the .json file when required. The default weight for "PrivateNetwork" is 2500, and the new weight | |
376 | # assigned to that id in the .json file is 6000. This increased weight means that when the "PrivateNetwork" key is | |
377 | # set to 'yes' (as above in the case of testfile.service) in the content of the unit file, the overall exposure | |
378 | # level for the unit file should decrease to account for that increased weight. | |
379 | cat <<EOF >/tmp/testfile.json | |
d54017e8 | 380 | {"UserOrDynamicUser": |
4b622119 | 381 | {"description_bad": "Service runs as root user", |
82100ef4 | 382 | "weight": 0, |
4b622119 MG |
383 | "range": 10 |
384 | }, | |
385 | "SupplementaryGroups": | |
386 | {"description_good": "Service has no supplementary groups", | |
387 | "description_bad": "Service runs with supplementary groups", | |
388 | "description_na": "Service runs as root, option does not matter", | |
389 | "weight": 200, | |
390 | "range": 1 | |
391 | }, | |
392 | "PrivateDevices": | |
393 | {"description_good": "Service has no access to hardware devices", | |
394 | "description_bad": "Service potentially has access to hardware devices", | |
395 | "weight": 1000, | |
396 | "range": 1 | |
397 | }, | |
398 | "PrivateMounts": | |
399 | {"description_good": "Service cannot install system mounts", | |
400 | "description_bad": "Service may install system mounts", | |
401 | "weight": 1000, | |
402 | "range": 1 | |
403 | }, | |
404 | "PrivateNetwork": | |
405 | {"description_good": "Service doesn't have access to the host's network", | |
406 | "description_bad": "Service has access to the host's network", | |
407 | "weight": 6000, | |
408 | "range": 1 | |
409 | }, | |
410 | "PrivateTmp": | |
411 | {"description_good": "Service has no access to other software's temporary files", | |
412 | "description_bad": "Service has access to other software's temporary files", | |
413 | "weight": 1000, | |
414 | "range": 1 | |
415 | }, | |
416 | "PrivateUsers": | |
417 | {"description_good": "Service does not have access to other users", | |
418 | "description_bad": "Service has access to other users", | |
419 | "weight": 1000, | |
420 | "range": 1 | |
421 | }, | |
422 | "ProtectControlGroups": | |
423 | {"description_good": "Service cannot modify the control group file system", | |
424 | "description_bad": "Service may modify the control group file system", | |
425 | "weight": 1000, | |
426 | "range": 1 | |
427 | }, | |
428 | "ProtectKernelModules": | |
429 | {"description_good": "Service cannot load or read kernel modules", | |
430 | "description_bad": "Service may load or read kernel modules", | |
431 | "weight": 1000, | |
432 | "range": 1 | |
433 | }, | |
434 | "ProtectKernelTunables": | |
435 | {"description_good": "Service cannot alter kernel tunables (/proc/sys, …)", | |
436 | "description_bad": "Service may alter kernel tunables", | |
437 | "weight": 1000, | |
438 | "range": 1 | |
439 | }, | |
440 | "ProtectKernelLogs": | |
441 | {"description_good": "Service cannot read from or write to the kernel log ring buffer", | |
442 | "description_bad": "Service may read from or write to the kernel log ring buffer", | |
443 | "weight": 1000, | |
444 | "range": 1 | |
445 | }, | |
446 | "ProtectClock": | |
447 | {"description_good": "Service cannot write to the hardware clock or system clock", | |
448 | "description_bad": "Service may write to the hardware clock or system clock", | |
449 | "weight": 1000, | |
450 | "range": 1 | |
451 | }, | |
452 | "ProtectHome": | |
453 | {"weight": 1000, | |
454 | "range": 10 | |
455 | }, | |
456 | "ProtectHostname": | |
457 | {"description_good": "Service cannot change system host/domainname", | |
458 | "description_bad": "Service may change system host/domainname", | |
459 | "weight": 50, | |
460 | "range": 1 | |
461 | }, | |
462 | "ProtectSystem": | |
463 | {"weight": 1000, | |
464 | "range": 10 | |
465 | }, | |
d54017e8 | 466 | "RootDirectoryOrRootImage": |
4b622119 MG |
467 | {"description_good": "Service has its own root directory/image", |
468 | "description_bad": "Service runs within the host's root directory", | |
469 | "weight": 200, | |
470 | "range": 1 | |
471 | }, | |
472 | "LockPersonality": | |
473 | {"description_good": "Service cannot change ABI personality", | |
474 | "description_bad": "Service may change ABI personality", | |
475 | "weight": 100, | |
476 | "range": 1 | |
477 | }, | |
478 | "MemoryDenyWriteExecute": | |
479 | {"description_good": "Service cannot create writable executable memory mappings", | |
480 | "description_bad": "Service may create writable executable memory mappings", | |
481 | "weight": 100, | |
482 | "range": 1 | |
483 | }, | |
484 | "NoNewPrivileges": | |
485 | {"description_good": "Service processes cannot acquire new privileges", | |
486 | "description_bad": "Service processes may acquire new privileges", | |
487 | "weight": 1000, | |
488 | "range": 1 | |
489 | }, | |
490 | "CapabilityBoundingSet_CAP_SYS_ADMIN": | |
491 | {"description_good": "Service has no administrator privileges", | |
492 | "description_bad": "Service has administrator privileges", | |
493 | "weight": 1500, | |
494 | "range": 1 | |
495 | }, | |
496 | "CapabilityBoundingSet_CAP_SET_UID_GID_PCAP": | |
497 | {"description_good": "Service cannot change UID/GID identities/capabilities", | |
498 | "description_bad": "Service may change UID/GID identities/capabilities", | |
499 | "weight": 1500, | |
500 | "range": 1 | |
501 | }, | |
502 | "CapabilityBoundingSet_CAP_SYS_PTRACE": | |
503 | {"description_good": "Service has no ptrace() debugging abilities", | |
504 | "description_bad": "Service has ptrace() debugging abilities", | |
505 | "weight": 1500, | |
506 | "range": 1 | |
507 | }, | |
508 | "CapabilityBoundingSet_CAP_SYS_TIME": | |
509 | {"description_good": "Service processes cannot change the system clock", | |
510 | "description_bad": "Service processes may change the system clock", | |
511 | "weight": 1000, | |
512 | "range": 1 | |
513 | }, | |
514 | "CapabilityBoundingSet_CAP_NET_ADMIN": | |
515 | {"description_good": "Service has no network configuration privileges", | |
516 | "description_bad": "Service has network configuration privileges", | |
517 | "weight": 1000, | |
518 | "range": 1 | |
519 | }, | |
520 | "CapabilityBoundingSet_CAP_SYS_RAWIO": | |
521 | {"description_good": "Service has no raw I/O access", | |
522 | "description_bad": "Service has raw I/O access", | |
523 | "weight": 1000, | |
524 | "range": 1 | |
525 | }, | |
526 | "CapabilityBoundingSet_CAP_SYS_MODULE": | |
527 | {"description_good": "Service cannot load kernel modules", | |
528 | "description_bad": "Service may load kernel modules", | |
529 | "weight": 1000, | |
530 | "range": 1 | |
531 | }, | |
532 | "CapabilityBoundingSet_CAP_AUDIT": | |
533 | {"description_good": "Service has no audit subsystem access", | |
534 | "description_bad": "Service has audit subsystem access", | |
535 | "weight": 500, | |
536 | "range": 1 | |
537 | }, | |
538 | "CapabilityBoundingSet_CAP_SYSLOG": | |
539 | {"description_good": "Service has no access to kernel logging", | |
540 | "description_bad": "Service has access to kernel logging", | |
541 | "weight": 500, | |
542 | "range": 1 | |
543 | }, | |
544 | "CapabilityBoundingSet_CAP_SYS_NICE_RESOURCE": | |
545 | {"description_good": "Service has no privileges to change resource use parameters", | |
546 | "description_bad": "Service has privileges to change resource use parameters", | |
547 | "weight": 500, | |
548 | "range": 1 | |
549 | }, | |
550 | "CapabilityBoundingSet_CAP_MKNOD": | |
551 | {"description_good": "Service cannot create device nodes", | |
552 | "description_bad": "Service may create device nodes", | |
553 | "weight": 500, | |
554 | "range": 1 | |
555 | }, | |
556 | "CapabilityBoundingSet_CAP_CHOWN_FSETID_SETFCAP": | |
557 | {"description_good": "Service cannot change file ownership/access mode/capabilities", | |
558 | "description_bad": "Service may change file ownership/access mode/capabilities unrestricted", | |
559 | "weight": 1000, | |
560 | "range": 1 | |
561 | }, | |
562 | "CapabilityBoundingSet_CAP_DAC_FOWNER_IPC_OWNER": | |
563 | {"description_good": "Service cannot override UNIX file/IPC permission checks", | |
564 | "description_bad": "Service may override UNIX file/IPC permission checks", | |
565 | "weight": 1000, | |
566 | "range": 1 | |
567 | }, | |
568 | "CapabilityBoundingSet_CAP_KILL": | |
569 | {"description_good": "Service cannot send UNIX signals to arbitrary processes", | |
570 | "description_bad": "Service may send UNIX signals to arbitrary processes", | |
571 | "weight": 500, | |
572 | "range": 1 | |
573 | }, | |
574 | "CapabilityBoundingSet_CAP_NET_BIND_SERVICE_BROADCAST_RAW": | |
575 | {"description_good": "Service has no elevated networking privileges", | |
576 | "description_bad": "Service has elevated networking privileges", | |
577 | "weight": 500, | |
578 | "range": 1 | |
579 | }, | |
580 | "CapabilityBoundingSet_CAP_SYS_BOOT": | |
581 | {"description_good": "Service cannot issue reboot()", | |
582 | "description_bad": "Service may issue reboot()", | |
583 | "weight": 100, | |
584 | "range": 1 | |
585 | }, | |
586 | "CapabilityBoundingSet_CAP_MAC": | |
587 | {"description_good": "Service cannot adjust SMACK MAC", | |
588 | "description_bad": "Service may adjust SMACK MAC", | |
589 | "weight": 100, | |
590 | "range": 1 | |
591 | }, | |
592 | "CapabilityBoundingSet_CAP_LINUX_IMMUTABLE": | |
593 | {"description_good": "Service cannot mark files immutable", | |
594 | "description_bad": "Service may mark files immutable", | |
595 | "weight": 75, | |
596 | "range": 1 | |
597 | }, | |
598 | "CapabilityBoundingSet_CAP_IPC_LOCK": | |
599 | {"description_good": "Service cannot lock memory into RAM", | |
600 | "description_bad": "Service may lock memory into RAM", | |
601 | "weight": 50, | |
602 | "range": 1 | |
603 | }, | |
604 | "CapabilityBoundingSet_CAP_SYS_CHROOT": | |
605 | {"description_good": "Service cannot issue chroot()", | |
606 | "description_bad": "Service may issue chroot()", | |
607 | "weight": 50, | |
608 | "range": 1 | |
609 | }, | |
610 | "CapabilityBoundingSet_CAP_BLOCK_SUSPEND": | |
611 | {"description_good": "Service cannot establish wake locks", | |
612 | "description_bad": "Service may establish wake locks", | |
613 | "weight": 25, | |
614 | "range": 1 | |
615 | }, | |
616 | "CapabilityBoundingSet_CAP_WAKE_ALARM": | |
617 | {"description_good": "Service cannot program timers that wake up the system", | |
618 | "description_bad": "Service may program timers that wake up the system", | |
619 | "weight": 25, | |
620 | "range": 1 | |
621 | }, | |
622 | "CapabilityBoundingSet_CAP_LEASE": | |
623 | {"description_good": "Service cannot create file leases", | |
624 | "description_bad": "Service may create file leases", | |
625 | "weight": 25, | |
626 | "range": 1 | |
627 | }, | |
628 | "CapabilityBoundingSet_CAP_SYS_TTY_CONFIG": | |
629 | {"description_good": "Service cannot issue vhangup()", | |
630 | "description_bad": "Service may issue vhangup()", | |
631 | "weight": 25, | |
632 | "range": 1 | |
633 | }, | |
634 | "CapabilityBoundingSet_CAP_SYS_PACCT": | |
635 | {"description_good": "Service cannot use acct()", | |
636 | "description_bad": "Service may use acct()", | |
637 | "weight": 25, | |
638 | "range": 1 | |
639 | }, | |
4f7a629e PH |
640 | "CapabilityBoundingSet_CAP_BPF": |
641 | {"description_good": "Service may load BPF programs", | |
642 | "description_bad": "Service may not load BPF programs", | |
643 | "weight": 25, | |
644 | "range": 1 | |
645 | }, | |
4b622119 MG |
646 | "UMask": |
647 | {"weight": 100, | |
648 | "range": 10 | |
649 | }, | |
650 | "KeyringMode": | |
651 | {"description_good": "Service doesn't share key material with other services", | |
652 | "description_bad": "Service shares key material with other service", | |
653 | "weight": 1000, | |
654 | "range": 1 | |
655 | }, | |
656 | "ProtectProc": | |
657 | {"description_good": "Service has restricted access to process tree(/proc hidepid=)", | |
658 | "description_bad": "Service has full access to process tree(/proc hidepid=)", | |
659 | "weight": 1000, | |
660 | "range": 3 | |
661 | }, | |
662 | "ProcSubset": | |
663 | {"description_good": "Service has no access to non-process/proc files(/proc subset=)", | |
664 | "description_bad": "Service has full access to non-process/proc files(/proc subset=)", | |
665 | "weight": 10, | |
666 | "range": 1 | |
667 | }, | |
668 | "NotifyAccess": | |
669 | {"description_good": "Service child processes cannot alter service state", | |
670 | "description_bad": "Service child processes may alter service state", | |
671 | "weight": 1000, | |
672 | "range": 1 | |
673 | }, | |
674 | "RemoveIPC": | |
675 | {"description_good": "Service user cannot leave SysV IPC objects around", | |
676 | "description_bad": "Service user may leave SysV IPC objects around", | |
677 | "description_na": "Service runs as root, option does not apply", | |
678 | "weight": 100, | |
679 | "range": 1 | |
680 | }, | |
681 | "Delegate": | |
682 | {"description_good": "Service does not maintain its own delegated control group subtree", | |
683 | "description_bad": "Service maintains its own delegated control group subtree", | |
684 | "weight": 100, | |
685 | "range": 1 | |
686 | }, | |
687 | "RestrictRealtime": | |
688 | {"description_good": "Service realtime scheduling access is restricted", | |
689 | "description_bad": "Service may acquire realtime scheduling", | |
690 | "weight": 500, | |
691 | "range": 1 | |
692 | }, | |
693 | "RestrictSUIDSGID": | |
694 | {"description_good": "SUID/SGIDfilecreationbyserviceisrestricted", | |
695 | "description_bad": "ServicemaycreateSUID/SGIDfiles", | |
696 | "weight": 1000, | |
697 | "range": 1 | |
698 | }, | |
c1e6f215 | 699 | "RestrictNamespaces_user": |
4b622119 MG |
700 | {"description_good": "Servicecannotcreateusernamespaces", |
701 | "description_bad": "Servicemaycreateusernamespaces", | |
702 | "weight": 1500, | |
703 | "range": 1 | |
704 | }, | |
c1e6f215 | 705 | "RestrictNamespaces_mnt": |
4b622119 MG |
706 | {"description_good": "Service cannot create file system namespaces", |
707 | "description_bad": "Service may create file system namespaces", | |
708 | "weight": 500, | |
709 | "range": 1 | |
710 | }, | |
c1e6f215 | 711 | "RestrictNamespaces_ipc": |
4b622119 MG |
712 | {"description_good": "Service cannot create IPC namespaces", |
713 | "description_bad": "Service may create IPC namespaces", | |
714 | "weight": 500, | |
715 | "range": 1 | |
716 | }, | |
c1e6f215 | 717 | "RestrictNamespaces_pid": |
4b622119 MG |
718 | {"description_good": "Service cannot create process namespaces", |
719 | "description_bad": "Service may create process namespaces", | |
720 | "weight": 500, | |
721 | "range": 1 | |
722 | }, | |
c1e6f215 | 723 | "RestrictNamespaces_cgroup": |
4b622119 MG |
724 | {"description_good": "Service cannot create cgroup namespaces", |
725 | "description_bad": "Service may create cgroup namespaces", | |
726 | "weight": 500, | |
727 | "range": 1 | |
728 | }, | |
c1e6f215 | 729 | "RestrictNamespaces_net": |
4b622119 MG |
730 | {"description_good": "Service cannot create network namespaces", |
731 | "description_bad": "Service may create network namespaces", | |
732 | "weight": 500, | |
733 | "range": 1 | |
734 | }, | |
c1e6f215 | 735 | "RestrictNamespaces_uts": |
4b622119 MG |
736 | {"description_good": "Service cannot create hostname namespaces", |
737 | "description_bad": "Service may create hostname namespaces", | |
738 | "weight": 100, | |
739 | "range": 1 | |
740 | }, | |
741 | "RestrictAddressFamilies_AF_INET_INET6": | |
742 | {"description_good": "Service cannot allocate Internet sockets", | |
743 | "description_bad": "Service may allocate Internet sockets", | |
744 | "weight": 1500, | |
745 | "range": 1 | |
746 | }, | |
747 | "RestrictAddressFamilies_AF_UNIX": | |
748 | {"description_good": "Service cannot allocate local sockets", | |
749 | "description_bad": "Service may allocate local sockets", | |
750 | "weight": 25, | |
751 | "range": 1 | |
752 | }, | |
753 | "RestrictAddressFamilies_AF_NETLINK": | |
754 | {"description_good": "Service cannot allocate netlink sockets", | |
755 | "description_bad": "Service may allocate netlink sockets", | |
756 | "weight": 200, | |
757 | "range": 1 | |
758 | }, | |
759 | "RestrictAddressFamilies_AF_PACKET": | |
760 | {"description_good": "Service cannot allocate packet sockets", | |
761 | "description_bad": "Service may allocate packet sockets", | |
762 | "weight": 1000, | |
763 | "range": 1 | |
764 | }, | |
765 | "RestrictAddressFamilies_OTHER": | |
766 | {"description_good": "Service cannot allocate exotic sockets", | |
767 | "description_bad": "Service may allocate exotic sockets", | |
768 | "weight": 1250, | |
769 | "range": 1 | |
770 | }, | |
771 | "SystemCallArchitectures": | |
772 | {"weight": 1000, | |
773 | "range": 10 | |
774 | }, | |
775 | "SystemCallFilter_swap": | |
776 | {"weight": 1000, | |
777 | "range": 10 | |
778 | }, | |
779 | "SystemCallFilter_obsolete": | |
780 | {"weight": 250, | |
781 | "range": 10 | |
782 | }, | |
783 | "SystemCallFilter_clock": | |
784 | {"weight": 1000, | |
785 | "range": 10 | |
786 | }, | |
787 | "SystemCallFilter_cpu_emulation": | |
788 | {"weight": 250, | |
789 | "range": 10 | |
790 | }, | |
791 | "SystemCallFilter_debug": | |
792 | {"weight": 1000, | |
793 | "range": 10 | |
794 | }, | |
795 | "SystemCallFilter_mount": | |
796 | {"weight": 1000, | |
797 | "range": 10 | |
798 | }, | |
799 | "SystemCallFilter_module": | |
800 | {"weight": 1000, | |
801 | "range": 10 | |
802 | }, | |
803 | "SystemCallFilter_raw_io": | |
804 | {"weight": 1000, | |
805 | "range": 10 | |
806 | }, | |
807 | "SystemCallFilter_reboot": | |
808 | {"weight": 1000, | |
809 | "range": 10 | |
810 | }, | |
811 | "SystemCallFilter_privileged": | |
812 | {"weight": 700, | |
813 | "range": 10 | |
814 | }, | |
815 | "SystemCallFilter_resources": | |
816 | {"weight": 700, | |
817 | "range": 10 | |
818 | }, | |
819 | "IPAddressDeny": | |
820 | {"weight": 1000, | |
821 | "range": 10 | |
822 | }, | |
823 | "DeviceAllow": | |
824 | {"weight": 1000, | |
825 | "range": 10 | |
826 | }, | |
827 | "AmbientCapabilities": | |
828 | {"description_good": "Service process does not receive ambient capabilities", | |
829 | "description_bad": "Service process receives ambient capabilities", | |
830 | "weight": 500, | |
831 | "range": 1 | |
832 | }, | |
833 | "INVALID_ID": | |
834 | {"weight": 1000, | |
835 | "range": 10 | |
836 | } | |
837 | } | |
838 | EOF | |
839 | ||
840 | # Reads in custom security requirements from the parsed .json file and uses these for comparison | |
841 | systemd-analyze security --threshold=90 --offline=true \ | |
842 | --security-policy=/tmp/testfile.json \ | |
843 | --root=/tmp/img/ testfile.service | |
844 | ||
04469211 | 845 | # The strict profile adds a lot of sanboxing options |
1449b0f8 | 846 | systemd-analyze security --threshold=25 --offline=true \ |
04469211 LB |
847 | --security-policy=/tmp/testfile.json \ |
848 | --profile=strict \ | |
849 | --root=/tmp/img/ testfile.service | |
850 | ||
04469211 | 851 | # The trusted profile doesn't add any sanboxing options |
128db0aa | 852 | (! systemd-analyze security --threshold=25 --offline=true \ |
04469211 LB |
853 | --security-policy=/tmp/testfile.json \ |
854 | --profile=/usr/lib/systemd/portable/profile/trusted/service.conf \ | |
128db0aa | 855 | --root=/tmp/img/ testfile.service) |
04469211 | 856 | |
128db0aa | 857 | (! systemd-analyze security --threshold=50 --offline=true \ |
4b622119 | 858 | --security-policy=/tmp/testfile.json \ |
128db0aa | 859 | --root=/tmp/img/ testfile.service) |
4b622119 MG |
860 | |
861 | rm /tmp/img/usr/lib/systemd/system/testfile.service | |
862 | ||
917e6554 LB |
863 | if systemd-analyze --version | grep -q -F "+ELFUTILS"; then |
864 | systemd-analyze inspect-elf --json=short /lib/systemd/systemd | grep -q -F '"elfType":"executable"' | |
865 | fi | |
866 | ||
444d9abd LB |
867 | systemd-analyze --threshold=90 security systemd-journald.service |
868 | ||
cf906bea YW |
869 | # issue 23663 |
870 | check() {( | |
871 | set +x | |
872 | output=$(systemd-analyze security --offline="${2?}" "${3?}" | grep -F 'SystemCallFilter=') | |
873 | assert_in "System call ${1?} list" "$output" | |
874 | assert_in "[+✓] SystemCallFilter=~@swap" "$output" | |
875 | assert_in "[+✓] SystemCallFilter=~@resources" "$output" | |
876 | assert_in "[+✓] SystemCallFilter=~@reboot" "$output" | |
877 | assert_in "[+✓] SystemCallFilter=~@raw-io" "$output" | |
878 | assert_in "[-✗] SystemCallFilter=~@privileged" "$output" | |
879 | assert_in "[+✓] SystemCallFilter=~@obsolete" "$output" | |
880 | assert_in "[+✓] SystemCallFilter=~@mount" "$output" | |
881 | assert_in "[+✓] SystemCallFilter=~@module" "$output" | |
882 | assert_in "[+✓] SystemCallFilter=~@debug" "$output" | |
883 | assert_in "[+✓] SystemCallFilter=~@cpu-emulation" "$output" | |
884 | assert_in "[-✗] SystemCallFilter=~@clock" "$output" | |
885 | )} | |
886 | ||
887 | export -n SYSTEMD_LOG_LEVEL | |
888 | ||
889 | mkdir -p /run/systemd/system | |
890 | cat >/run/systemd/system/allow-list.service <<EOF | |
891 | [Service] | |
892 | ExecStart=false | |
893 | SystemCallFilter=@system-service | |
894 | SystemCallFilter=~@resources:ENOANO @privileged | |
895 | SystemCallFilter=@clock | |
896 | EOF | |
897 | ||
898 | cat >/run/systemd/system/deny-list.service <<EOF | |
899 | [Service] | |
900 | ExecStart=false | |
901 | SystemCallFilter=~@known | |
902 | SystemCallFilter=@system-service | |
903 | SystemCallFilter=~@resources:ENOANO @privileged | |
904 | SystemCallFilter=@clock | |
905 | EOF | |
906 | ||
907 | systemctl daemon-reload | |
908 | ||
909 | check allow yes /run/systemd/system/allow-list.service | |
910 | check allow no allow-list.service | |
911 | check deny yes /run/systemd/system/deny-list.service | |
912 | check deny no deny-list.service | |
913 | ||
914 | output=$(systemd-run -p "SystemCallFilter=@system-service" -p "SystemCallFilter=~@resources:ENOANO @privileged" -p "SystemCallFilter=@clock" sleep 60 2>&1) | |
7693661a | 915 | name=$(echo "$output" | awk '{ print $4 }' | cut -d';' -f1) |
cf906bea YW |
916 | |
917 | check allow yes /run/systemd/transient/"$name" | |
918 | check allow no "$name" | |
919 | ||
920 | output=$(systemd-run -p "SystemCallFilter=~@known" -p "SystemCallFilter=@system-service" -p "SystemCallFilter=~@resources:ENOANO @privileged" -p "SystemCallFilter=@clock" sleep 60 2>&1) | |
7693661a | 921 | name=$(echo "$output" | awk '{ print $4 }' | cut -d';' -f1) |
cf906bea YW |
922 | |
923 | check deny yes /run/systemd/transient/"$name" | |
924 | check deny no "$name" | |
925 | ||
a62e12da LP |
926 | # Let's also test the "image-policy" verb |
927 | ||
928 | systemd-analyze image-policy '*' 2>&1 | grep -q -F "Long form: =verity+signed+encrypted+unprotected+unused+absent" | |
929 | systemd-analyze image-policy '-' 2>&1 | grep -q -F "Long form: =unused+absent" | |
930 | systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -F "Long form: usr=verity:home=encrypted:=unused+absent" | |
931 | systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^home \+encrypted \+' | |
932 | systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^usr \+verity \+' | |
933 | systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^root \+ignore \+' | |
934 | systemd-analyze image-policy 'home=encrypted:usr=verity' 2>&1 | grep -q -e '^usr-verity \+unprotected \+' | |
935 | ||
128db0aa | 936 | (! systemd-analyze image-policy 'doedel') |
a62e12da | 937 | |
f70c90f5 LP |
938 | # Output is very hard to predict, but let's run it for coverage anyway |
939 | systemd-analyze pcrs | |
940 | systemd-analyze pcrs --json=pretty | |
941 | systemd-analyze pcrs 14 7 0 ima | |
942 | ||
fb8cc599 LP |
943 | systemd-analyze architectures |
944 | systemd-analyze architectures --json=pretty | |
945 | systemd-analyze architectures x86 | |
946 | systemd-analyze architectures x86-64 | |
947 | systemd-analyze architectures native | |
948 | systemd-analyze architectures uname | |
949 | ||
4b622119 MG |
950 | systemd-analyze log-level info |
951 | ||
07268394 | 952 | touch /testok |