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