1#!/usr/bin/env bash
2# SPDX-License-Identifier: LGPL-2.1-or-later
3# shellcheck disable=SC2016
4set -eux
5
6systemd-analyze log-level debug
7export SYSTEMD_LOG_LEVEL=debug
8
9mkdir -p /tmp/img/usr/lib/systemd/system/
10mkdir -p /tmp/img/opt/
11
12touch /tmp/img/opt/script0.sh
13chmod +x /tmp/img/opt/script0.sh
14
15cat <<EOF >/tmp/img/usr/lib/systemd/system/testfile.service
16[Service]
17ExecStart = /opt/script0.sh
18EOF
19
20set +e
21# Default behaviour is to recurse through all dependencies when unit is loaded
22systemd-analyze verify --root=/tmp/img/ testfile.service \
23    && { echo 'unexpected success'; exit 1; }
24
25# As above, recurses through all dependencies when unit is loaded
26systemd-analyze verify --recursive-errors=yes --root=/tmp/img/ testfile.service \
27    && { echo 'unexpected success'; exit 1; }
28
29# Recurses through unit file and its direct dependencies when unit is loaded
30systemd-analyze verify --recursive-errors=one --root=/tmp/img/ testfile.service \
31    && { echo 'unexpected success'; exit 1; }
32
33set -e
34
35# zero exit status since dependencies are ignored when unit is loaded
36systemd-analyze verify --recursive-errors=no --root=/tmp/img/ testfile.service
37
38rm /tmp/img/usr/lib/systemd/system/testfile.service
39
40cat <<EOF >/tmp/testfile.service
41[Unit]
42foo = bar
43
44[Service]
45ExecStart = echo hello
46EOF
47
48cat <<EOF >/tmp/testfile2.service
49[Unit]
50Requires = testfile.service
51
52[Service]
53ExecStart = echo hello
54EOF
55
56# Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded
57systemd-analyze verify --recursive-errors=no /tmp/testfile2.service
58
59set +e
60# Non-zero exit status since all associated dependencies are recursively loaded when the unit file is loaded
61systemd-analyze verify --recursive-errors=yes /tmp/testfile2.service \
62    && { echo 'unexpected success'; exit 1; }
63set -e
64
65rm /tmp/testfile.service
66rm /tmp/testfile2.service
67
68cat <<EOF >/tmp/testfile.service
69[Service]
70ExecStart = echo hello
71DeviceAllow=/dev/sda
72EOF
73
74# Prevent regression from #13380 and #20859 where we can't verify hidden files
75cp /tmp/testfile.service /tmp/.testfile.service
76
77systemd-analyze verify /tmp/.testfile.service
78
79rm /tmp/.testfile.service
80
81# Alias a unit file's name on disk (see #20061)
82cp /tmp/testfile.service /tmp/testsrvc
83
84systemd-analyze verify /tmp/testsrvc \
85    && { echo 'unexpected success'; exit 1; }
86
87systemd-analyze verify /tmp/testsrvc:alias.service
88
89# Zero exit status since the value used for comparison determine exposure to security threats is by default 100
90systemd-analyze security --offline=true /tmp/testfile.service
91
92set +e
93#The overall exposure level assigned to the unit is greater than the set threshold
94systemd-analyze security --threshold=90 --offline=true /tmp/testfile.service \
95    && { echo 'unexpected success'; exit 1; }
96set -e
97
98# Ensure we print the list of ACLs, see https://github.com/systemd/systemd/issues/23185
99systemd-analyze security --offline=true /tmp/testfile.service | grep -q -F "/dev/sda"
100
101rm /tmp/testfile.service
102
103cat <<EOF >/tmp/img/usr/lib/systemd/system/testfile.service
104[Service]
105ExecStart = echo hello
106PrivateNetwork = yes
107PrivateDevices = yes
108PrivateUsers = yes
109EOF
110
111# The new overall exposure level assigned to the unit is less than the set thresholds
112# Verifies that the --offline= option works with --root=
113systemd-analyze security --threshold=90 --offline=true --root=/tmp/img/ testfile.service
114
115# Added an additional "INVALID_ID" id to the .json to verify that nothing breaks when input is malformed
116# The PrivateNetwork id description and weight was changed to verify that 'security' is actually reading in
117# values from the .json file when required. The default weight for "PrivateNetwork" is 2500, and the new weight
118# assigned to that id in the .json file is 6000. This increased weight means that when the "PrivateNetwork" key is
119# set to 'yes' (as above in the case of testfile.service) in the content of the unit file, the overall exposure
120# level for the unit file should decrease to account for that increased weight.
121cat <<EOF >/tmp/testfile.json
122{"UserOrDynamicUser":
123    {"description_bad": "Service runs as root user",
124    "weight": 0,
125    "range": 10
126    },
127"SupplementaryGroups":
128    {"description_good": "Service has no supplementary groups",
129    "description_bad": "Service runs with supplementary groups",
130    "description_na": "Service runs as root, option does not matter",
131    "weight": 200,
132    "range": 1
133    },
134"PrivateDevices":
135    {"description_good": "Service has no access to hardware devices",
136    "description_bad": "Service potentially has access to hardware devices",
137    "weight": 1000,
138    "range": 1
139    },
140"PrivateMounts":
141    {"description_good": "Service cannot install system mounts",
142    "description_bad": "Service may install system mounts",
143    "weight": 1000,
144    "range": 1
145    },
146"PrivateNetwork":
147    {"description_good": "Service doesn't have access to the host's network",
148    "description_bad": "Service has access to the host's network",
149    "weight": 6000,
150    "range": 1
151    },
152"PrivateTmp":
153    {"description_good": "Service has no access to other software's temporary files",
154    "description_bad": "Service has access to other software's temporary files",
155    "weight": 1000,
156    "range": 1
157    },
158"PrivateUsers":
159    {"description_good": "Service does not have access to other users",
160    "description_bad": "Service has access to other users",
161    "weight": 1000,
162    "range": 1
163    },
164"ProtectControlGroups":
165    {"description_good": "Service cannot modify the control group file system",
166    "description_bad": "Service may modify the control group file system",
167    "weight": 1000,
168    "range": 1
169    },
170"ProtectKernelModules":
171    {"description_good": "Service cannot load or read kernel modules",
172    "description_bad": "Service may load or read kernel modules",
173    "weight": 1000,
174    "range": 1
175    },
176"ProtectKernelTunables":
177    {"description_good": "Service cannot alter kernel tunables (/proc/sys, …)",
178    "description_bad": "Service may alter kernel tunables",
179    "weight": 1000,
180    "range": 1
181    },
182"ProtectKernelLogs":
183    {"description_good": "Service cannot read from or write to the kernel log ring buffer",
184    "description_bad": "Service may read from or write to the kernel log ring buffer",
185    "weight": 1000,
186    "range": 1
187    },
188"ProtectClock":
189    {"description_good": "Service cannot write to the hardware clock or system clock",
190    "description_bad": "Service may write to the hardware clock or system clock",
191    "weight": 1000,
192    "range": 1
193    },
194"ProtectHome":
195    {"weight": 1000,
196    "range": 10
197    },
198"ProtectHostname":
199    {"description_good": "Service cannot change system host/domainname",
200    "description_bad": "Service may change system host/domainname",
201    "weight": 50,
202    "range": 1
203    },
204"ProtectSystem":
205    {"weight": 1000,
206    "range": 10
207    },
208"RootDirectoryOrRootImage":
209    {"description_good": "Service has its own root directory/image",
210    "description_bad": "Service runs within the host's root directory",
211    "weight": 200,
212    "range": 1
213    },
214"LockPersonality":
215    {"description_good": "Service cannot change ABI personality",
216    "description_bad": "Service may change ABI personality",
217    "weight": 100,
218    "range": 1
219    },
220"MemoryDenyWriteExecute":
221    {"description_good": "Service cannot create writable executable memory mappings",
222    "description_bad": "Service may create writable executable memory mappings",
223    "weight": 100,
224    "range": 1
225    },
226"NoNewPrivileges":
227    {"description_good": "Service processes cannot acquire new privileges",
228    "description_bad": "Service processes may acquire new privileges",
229    "weight": 1000,
230    "range": 1
231    },
232"CapabilityBoundingSet_CAP_SYS_ADMIN":
233    {"description_good": "Service has no administrator privileges",
234    "description_bad": "Service has administrator privileges",
235    "weight": 1500,
236    "range": 1
237    },
238"CapabilityBoundingSet_CAP_SET_UID_GID_PCAP":
239    {"description_good": "Service cannot change UID/GID identities/capabilities",
240    "description_bad": "Service may change UID/GID identities/capabilities",
241    "weight": 1500,
242    "range": 1
243    },
244"CapabilityBoundingSet_CAP_SYS_PTRACE":
245    {"description_good": "Service has no ptrace() debugging abilities",
246    "description_bad": "Service has ptrace() debugging abilities",
247    "weight": 1500,
248    "range": 1
249    },
250"CapabilityBoundingSet_CAP_SYS_TIME":
251    {"description_good": "Service processes cannot change the system clock",
252    "description_bad": "Service processes may change the system clock",
253    "weight": 1000,
254    "range": 1
255    },
256"CapabilityBoundingSet_CAP_NET_ADMIN":
257    {"description_good": "Service has no network configuration privileges",
258    "description_bad": "Service has network configuration privileges",
259    "weight": 1000,
260    "range": 1
261    },
262"CapabilityBoundingSet_CAP_SYS_RAWIO":
263    {"description_good": "Service has no raw I/O access",
264    "description_bad": "Service has raw I/O access",
265    "weight": 1000,
266    "range": 1
267    },
268"CapabilityBoundingSet_CAP_SYS_MODULE":
269    {"description_good": "Service cannot load kernel modules",
270    "description_bad": "Service may load kernel modules",
271    "weight": 1000,
272    "range": 1
273    },
274"CapabilityBoundingSet_CAP_AUDIT":
275    {"description_good": "Service has no audit subsystem access",
276    "description_bad": "Service has audit subsystem access",
277    "weight": 500,
278    "range": 1
279    },
280"CapabilityBoundingSet_CAP_SYSLOG":
281    {"description_good": "Service has no access to kernel logging",
282    "description_bad": "Service has access to kernel logging",
283    "weight": 500,
284    "range": 1
285    },
286"CapabilityBoundingSet_CAP_SYS_NICE_RESOURCE":
287    {"description_good": "Service has no privileges to change resource use parameters",
288    "description_bad": "Service has privileges to change resource use parameters",
289    "weight": 500,
290    "range": 1
291    },
292"CapabilityBoundingSet_CAP_MKNOD":
293    {"description_good": "Service cannot create device nodes",
294    "description_bad": "Service may create device nodes",
295    "weight": 500,
296    "range": 1
297    },
298"CapabilityBoundingSet_CAP_CHOWN_FSETID_SETFCAP":
299    {"description_good": "Service cannot change file ownership/access mode/capabilities",
300    "description_bad": "Service may change file ownership/access mode/capabilities unrestricted",
301    "weight": 1000,
302    "range": 1
303    },
304"CapabilityBoundingSet_CAP_DAC_FOWNER_IPC_OWNER":
305    {"description_good": "Service cannot override UNIX file/IPC permission checks",
306    "description_bad": "Service may override UNIX file/IPC permission checks",
307    "weight": 1000,
308    "range": 1
309    },
310"CapabilityBoundingSet_CAP_KILL":
311    {"description_good": "Service cannot send UNIX signals to arbitrary processes",
312    "description_bad": "Service may send UNIX signals to arbitrary processes",
313    "weight": 500,
314    "range": 1
315    },
316"CapabilityBoundingSet_CAP_NET_BIND_SERVICE_BROADCAST_RAW":
317    {"description_good": "Service has no elevated networking privileges",
318    "description_bad": "Service has elevated networking privileges",
319    "weight": 500,
320    "range": 1
321    },
322"CapabilityBoundingSet_CAP_SYS_BOOT":
323    {"description_good": "Service cannot issue reboot()",
324    "description_bad": "Service may issue reboot()",
325    "weight": 100,
326    "range": 1
327    },
328"CapabilityBoundingSet_CAP_MAC":
329    {"description_good": "Service cannot adjust SMACK MAC",
330    "description_bad": "Service may adjust SMACK MAC",
331    "weight": 100,
332    "range": 1
333    },
334"CapabilityBoundingSet_CAP_LINUX_IMMUTABLE":
335    {"description_good": "Service cannot mark files immutable",
336    "description_bad": "Service may mark files immutable",
337    "weight": 75,
338    "range": 1
339    },
340"CapabilityBoundingSet_CAP_IPC_LOCK":
341    {"description_good": "Service cannot lock memory into RAM",
342    "description_bad": "Service may lock memory into RAM",
343    "weight": 50,
344    "range": 1
345    },
346"CapabilityBoundingSet_CAP_SYS_CHROOT":
347    {"description_good": "Service cannot issue chroot()",
348    "description_bad": "Service may issue chroot()",
349    "weight": 50,
350    "range": 1
351    },
352"CapabilityBoundingSet_CAP_BLOCK_SUSPEND":
353    {"description_good": "Service cannot establish wake locks",
354    "description_bad": "Service may establish wake locks",
355    "weight": 25,
356    "range": 1
357    },
358"CapabilityBoundingSet_CAP_WAKE_ALARM":
359    {"description_good": "Service cannot program timers that wake up the system",
360    "description_bad": "Service may program timers that wake up the system",
361    "weight": 25,
362    "range": 1
363    },
364"CapabilityBoundingSet_CAP_LEASE":
365    {"description_good": "Service cannot create file leases",
366    "description_bad": "Service may create file leases",
367    "weight": 25,
368    "range": 1
369    },
370"CapabilityBoundingSet_CAP_SYS_TTY_CONFIG":
371    {"description_good": "Service cannot issue vhangup()",
372    "description_bad": "Service may issue vhangup()",
373    "weight": 25,
374    "range": 1
375    },
376"CapabilityBoundingSet_CAP_SYS_PACCT":
377    {"description_good": "Service cannot use acct()",
378    "description_bad": "Service may use acct()",
379    "weight": 25,
380    "range": 1
381    },
382"UMask":
383    {"weight": 100,
384    "range": 10
385    },
386"KeyringMode":
387    {"description_good": "Service doesn't share key material with other services",
388    "description_bad": "Service shares key material with other service",
389    "weight": 1000,
390    "range": 1
391    },
392"ProtectProc":
393    {"description_good": "Service has restricted access to process tree(/proc hidepid=)",
394    "description_bad": "Service has full access to process tree(/proc hidepid=)",
395    "weight": 1000,
396    "range": 3
397    },
398"ProcSubset":
399    {"description_good": "Service has no access to non-process/proc files(/proc subset=)",
400    "description_bad": "Service has full access to non-process/proc files(/proc subset=)",
401    "weight": 10,
402    "range": 1
403    },
404"NotifyAccess":
405    {"description_good": "Service child processes cannot alter service state",
406    "description_bad": "Service child processes may alter service state",
407    "weight": 1000,
408    "range": 1
409    },
410"RemoveIPC":
411    {"description_good": "Service user cannot leave SysV IPC objects around",
412    "description_bad": "Service user may leave SysV IPC objects around",
413    "description_na": "Service runs as root, option does not apply",
414    "weight": 100,
415    "range": 1
416    },
417"Delegate":
418    {"description_good": "Service does not maintain its own delegated control group subtree",
419    "description_bad": "Service maintains its own delegated control group subtree",
420    "weight": 100,
421    "range": 1
422    },
423"RestrictRealtime":
424    {"description_good": "Service realtime scheduling access is restricted",
425    "description_bad": "Service may acquire realtime scheduling",
426    "weight": 500,
427    "range": 1
428    },
429"RestrictSUIDSGID":
430    {"description_good": "SUID/SGIDfilecreationbyserviceisrestricted",
431    "description_bad": "ServicemaycreateSUID/SGIDfiles",
432    "weight": 1000,
433    "range": 1
434    },
435"RestrictNamespaces_user":
436    {"description_good": "Servicecannotcreateusernamespaces",
437    "description_bad": "Servicemaycreateusernamespaces",
438    "weight": 1500,
439    "range": 1
440    },
441"RestrictNamespaces_mnt":
442    {"description_good": "Service cannot create file system namespaces",
443    "description_bad": "Service may create file system namespaces",
444    "weight": 500,
445    "range": 1
446    },
447"RestrictNamespaces_ipc":
448    {"description_good": "Service cannot create IPC namespaces",
449    "description_bad": "Service may create IPC namespaces",
450    "weight": 500,
451    "range": 1
452    },
453"RestrictNamespaces_pid":
454    {"description_good": "Service cannot create process namespaces",
455    "description_bad": "Service may create process namespaces",
456    "weight": 500,
457    "range": 1
458    },
459"RestrictNamespaces_cgroup":
460    {"description_good": "Service cannot create cgroup namespaces",
461    "description_bad": "Service may create cgroup namespaces",
462    "weight": 500,
463    "range": 1
464    },
465"RestrictNamespaces_net":
466    {"description_good": "Service cannot create network namespaces",
467    "description_bad": "Service may create network namespaces",
468    "weight": 500,
469    "range": 1
470    },
471"RestrictNamespaces_uts":
472    {"description_good": "Service cannot create hostname namespaces",
473    "description_bad": "Service may create hostname namespaces",
474    "weight": 100,
475    "range": 1
476    },
477"RestrictAddressFamilies_AF_INET_INET6":
478    {"description_good": "Service cannot allocate Internet sockets",
479    "description_bad": "Service may allocate Internet sockets",
480    "weight": 1500,
481    "range": 1
482    },
483"RestrictAddressFamilies_AF_UNIX":
484    {"description_good": "Service cannot allocate local sockets",
485    "description_bad": "Service may allocate local sockets",
486    "weight": 25,
487    "range": 1
488    },
489"RestrictAddressFamilies_AF_NETLINK":
490    {"description_good": "Service cannot allocate netlink sockets",
491    "description_bad": "Service may allocate netlink sockets",
492    "weight": 200,
493    "range": 1
494    },
495"RestrictAddressFamilies_AF_PACKET":
496    {"description_good": "Service cannot allocate packet sockets",
497    "description_bad": "Service may allocate packet sockets",
498    "weight": 1000,
499    "range": 1
500    },
501"RestrictAddressFamilies_OTHER":
502    {"description_good": "Service cannot allocate exotic sockets",
503    "description_bad": "Service may allocate exotic sockets",
504    "weight": 1250,
505    "range": 1
506    },
507"SystemCallArchitectures":
508    {"weight": 1000,
509    "range": 10
510    },
511"SystemCallFilter_swap":
512    {"weight": 1000,
513    "range": 10
514    },
515"SystemCallFilter_obsolete":
516    {"weight": 250,
517    "range": 10
518    },
519"SystemCallFilter_clock":
520    {"weight": 1000,
521    "range": 10
522    },
523"SystemCallFilter_cpu_emulation":
524    {"weight": 250,
525    "range": 10
526    },
527"SystemCallFilter_debug":
528    {"weight": 1000,
529    "range": 10
530    },
531"SystemCallFilter_mount":
532    {"weight": 1000,
533    "range": 10
534    },
535"SystemCallFilter_module":
536    {"weight": 1000,
537    "range": 10
538    },
539"SystemCallFilter_raw_io":
540    {"weight": 1000,
541    "range": 10
542    },
543"SystemCallFilter_reboot":
544    {"weight": 1000,
545    "range": 10
546    },
547"SystemCallFilter_privileged":
548    {"weight": 700,
549    "range": 10
550    },
551"SystemCallFilter_resources":
552    {"weight": 700,
553    "range": 10
554    },
555"IPAddressDeny":
556    {"weight": 1000,
557    "range": 10
558    },
559"DeviceAllow":
560    {"weight": 1000,
561    "range": 10
562    },
563"AmbientCapabilities":
564    {"description_good": "Service process does not receive ambient capabilities",
565    "description_bad": "Service process receives ambient capabilities",
566    "weight": 500,
567    "range": 1
568    },
569"INVALID_ID":
570    {"weight": 1000,
571    "range": 10
572    }
573}
574EOF
575
576# Reads in custom security requirements from the parsed .json file and uses these for comparison
577systemd-analyze security --threshold=90 --offline=true \
578                           --security-policy=/tmp/testfile.json \
579                           --root=/tmp/img/ testfile.service
580
581# The strict profile adds a lot of sanboxing options
582systemd-analyze security --threshold=25 --offline=true \
583                           --security-policy=/tmp/testfile.json \
584                           --profile=strict \
585                           --root=/tmp/img/ testfile.service
586
587set +e
588# The trusted profile doesn't add any sanboxing options
589systemd-analyze security --threshold=25 --offline=true \
590                           --security-policy=/tmp/testfile.json \
591                           --profile=/usr/lib/systemd/portable/profile/trusted/service.conf \
592                           --root=/tmp/img/ testfile.service \
593    && { echo 'unexpected success'; exit 1; }
594
595systemd-analyze security --threshold=50 --offline=true \
596                           --security-policy=/tmp/testfile.json \
597                           --root=/tmp/img/ testfile.service \
598    && { echo 'unexpected success'; exit 1; }
599set -e
600
601rm /tmp/img/usr/lib/systemd/system/testfile.service
602
603if systemd-analyze --version | grep -q -F "+ELFUTILS"; then
604    systemd-analyze inspect-elf --json=short /lib/systemd/systemd | grep -q -F '"elfType":"executable"'
605fi
606
607systemd-analyze --threshold=90 security systemd-journald.service
608
609systemd-analyze log-level info
610
611echo OK >/testok
612
613exit 0
614