2021-08-25 09:44:26 -07:00
#!/usr/bin/env bash
2021-10-17 18:13:06 +02:00
# SPDX-License-Identifier: LGPL-2.1-or-later
2021-08-25 09:44:26 -07:00
# shellcheck disable=SC2016
set -eux
2023-05-16 19:09:13 +02:00
# shellcheck source=test/units/util.sh
. " $( dirname " $0 " ) " /util.sh
2022-06-16 03:21:28 +09:00
2022-11-03 10:59:38 +01:00
systemctl log-level debug
2021-11-30 23:49:58 +00:00
export SYSTEMD_LOG_LEVEL = debug
2021-08-25 09:44:26 -07:00
2022-11-02 17:51:51 +01:00
# Sanity checks
#
2023-04-10 03:40:49 +09:00
# We can't really test time, critical-chain and plot verbs here, as
2022-11-02 17:51:51 +01:00
# the testsuite service is a part of the boot transaction, so let's assume
# they fail
systemd-analyze || :
systemd-analyze time || :
systemd-analyze critical-chain || :
2023-04-10 03:40:49 +09:00
# blame
systemd-analyze blame
systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame
2023-01-13 09:17:27 +00:00
# plot
2022-11-02 17:51:51 +01:00
systemd-analyze plot >/dev/null || :
2023-01-13 09:17:27 +00:00
systemd-analyze plot --json= pretty >/dev/null || :
systemd-analyze plot --json= short >/dev/null || :
systemd-analyze plot --json= off >/dev/null || :
systemd-analyze plot --json= pretty --no-legend >/dev/null || :
systemd-analyze plot --json= short --no-legend >/dev/null || :
systemd-analyze plot --json= off --no-legend >/dev/null || :
systemd-analyze plot --table >/dev/null || :
systemd-analyze plot --table --no-legend >/dev/null || :
2022-11-03 10:59:38 +01:00
# legacy/deprecated options (moved to systemctl, but still usable from analyze)
systemd-analyze log-level
systemd-analyze log-level " $( systemctl log-level) "
systemd-analyze get-log-level
systemd-analyze set-log-level " $( systemctl log-level) "
systemd-analyze log-target
systemd-analyze log-target " $( systemctl log-target) "
systemd-analyze get-log-target
systemd-analyze set-log-target " $( systemctl log-target) "
systemd-analyze service-watchdogs
systemd-analyze service-watchdogs " $( systemctl service-watchdogs) "
2022-11-02 17:51:51 +01:00
# dot
systemd-analyze dot >/dev/null
systemd-analyze dot systemd-journald.service >/dev/null
systemd-analyze dot systemd-journald.service systemd-logind.service >/dev/null
systemd-analyze dot --from-pattern= "*" --from-pattern= "*.service" systemd-journald.service >/dev/null
systemd-analyze dot --to-pattern= "*" --to-pattern= "*.service" systemd-journald.service >/dev/null
systemd-analyze dot --from-pattern= "*.service" --to-pattern= "*.service" systemd-journald.service >/dev/null
systemd-analyze dot --order systemd-journald.service systemd-logind.service >/dev/null
systemd-analyze dot --require systemd-journald.service systemd-logind.service >/dev/null
systemd-analyze dot "systemd-*.service" >/dev/null
( ! systemd-analyze dot systemd-journald.service systemd-logind.service "*" bbb ccc)
# dump
2023-04-27 23:23:30 +01:00
# this should be rate limited to 10 calls in 10 minutes for unprivileged callers
for _ in { 1..10} ; do
runas testuser systemd-analyze dump systemd-journald.service >/dev/null
done
( ! runas testuser systemd-analyze dump >/dev/null)
# still limited after a reload
systemctl daemon-reload
( ! runas testuser systemd-analyze dump >/dev/null)
# and a re-exec
systemctl daemon-reexec
( ! runas testuser systemd-analyze dump >/dev/null)
# privileged call, so should not be rate limited
for _ in { 1..10} ; do
systemd-analyze dump systemd-journald.service >/dev/null
done
2022-11-02 17:51:51 +01:00
systemd-analyze dump >/dev/null
systemd-analyze dump "*" >/dev/null
systemd-analyze dump "*.socket" >/dev/null
2022-11-03 11:33:13 +01:00
systemd-analyze dump "*.socket" "*.service" aaaaaaa ... >/dev/null
2022-11-02 17:51:51 +01:00
systemd-analyze dump systemd-journald.service >/dev/null
2023-01-26 13:28:15 +00:00
systemd-analyze malloc >/dev/null
2022-11-02 17:51:51 +01:00
( ! systemd-analyze dump "" )
2022-11-03 11:33:13 +01:00
# unit-files
systemd-analyze unit-files >/dev/null
systemd-analyze unit-files systemd-journald.service >/dev/null
systemd-analyze unit-files "*" >/dev/null
systemd-analyze unit-files "*" aaaaaa "*.service" "*.target" >/dev/null
systemd-analyze unit-files --user >/dev/null
systemd-analyze unit-files --user "*" aaaaaa "*.service" "*.target" >/dev/null
2022-11-02 17:51:51 +01:00
# unit-paths
systemd-analyze unit-paths
systemd-analyze unit-paths --user
systemd-analyze unit-paths --global
# exist-status
systemd-analyze exit-status
systemd-analyze exit-status STDOUT BPF
systemd-analyze exit-status 0 1 { 63..65}
( ! systemd-analyze exit-status STDOUT BPF "hello*" )
# capability
systemd-analyze capability
systemd-analyze capability cap_chown CAP_KILL
systemd-analyze capability 0 1 { 30..32}
( ! systemd-analyze capability cap_chown CAP_KILL "hello*" )
# condition
mkdir -p /run/systemd/system
UNIT_NAME = " analyze-condition- $RANDOM .service "
cat >" /run/systemd/system/ $UNIT_NAME " <<EOF
[ Unit]
AssertPathExists = /etc/os-release
AssertEnvironment = !FOOBAR
ConditionKernelVersion = >1.0
ConditionPathExists = /etc/os-release
[ Service]
ExecStart = /bin/true
EOF
systemctl daemon-reload
systemd-analyze condition --unit= " $UNIT_NAME "
systemd-analyze condition 'ConditionKernelVersion = ! <4.0' \
'ConditionKernelVersion = >=3.1' \
'ConditionACPower=|false' \
'ConditionArchitecture=|!arm' \
'AssertPathExists=/etc/os-release'
( ! systemd-analyze condition 'ConditionArchitecture=|!arm' 'AssertXYZ=foo' )
( ! systemd-analyze condition 'ConditionKernelVersion=<1.0' )
( ! systemd-analyze condition 'AssertKernelVersion=<1.0' )
# syscall-filter
systemd-analyze syscall-filter >/dev/null
systemd-analyze syscall-filter @chown @sync
systemd-analyze syscall-filter @sync @sync @sync
( ! systemd-analyze syscall-filter @chown @sync @foobar)
# filesystems (requires libbpf support)
if systemctl --version | grep "+BPF_FRAMEWORK" ; then
systemd-analyze filesystems >/dev/null
systemd-analyze filesystems @basic-api
systemd-analyze filesystems @basic-api @basic-api @basic-api
( ! systemd-analyze filesystems @basic-api @basic-api @foobar @basic-api)
fi
# calendar
systemd-analyze calendar '*-2-29 0:0:0'
systemd-analyze calendar --iterations= 5 '*-2-29 0:0:0'
systemd-analyze calendar '*-* *:*:*'
systemd-analyze calendar --iterations= 5 '*-* *:*:*'
systemd-analyze calendar --iterations= 50 '*-* *:*:*'
systemd-analyze calendar --iterations= 0 '*-* *:*:*'
2022-11-03 11:33:13 +01:00
systemd-analyze calendar --iterations= 5 '01-01-22 01:00:00'
2022-11-02 17:51:51 +01:00
systemd-analyze calendar --base-time= yesterday --iterations= 5 '*-* *:*:*'
( ! systemd-analyze calendar --iterations= 0 '*-* 99:*:*' )
( ! systemd-analyze calendar --base-time= never '*-* *:*:*' )
( ! systemd-analyze calendar 1)
( ! systemd-analyze calendar "" )
# timestamp
systemd-analyze timestamp now
systemd-analyze timestamp -- -1
systemd-analyze timestamp yesterday now tomorrow
( ! systemd-analyze timestamp yesterday never tomorrow)
( ! systemd-analyze timestamp 1)
2022-11-03 11:33:13 +01:00
( ! systemd-analyze timestamp '*-2-29 0:0:0' )
2022-11-02 17:51:51 +01:00
( ! systemd-analyze timestamp "" )
# timespan
systemd-analyze timespan 1
systemd-analyze timespan 1s 300s '1year 0.000001s'
( ! systemd-analyze timespan 1s 300s aaaaaa '1year 0.000001s' )
( ! systemd-analyze timespan -- -1)
2022-11-03 11:33:13 +01:00
( ! systemd-analyze timespan '*-2-29 0:0:0' )
2022-11-02 17:51:51 +01:00
( ! systemd-analyze timespan "" )
# cat-config
systemd-analyze cat-config systemd/system.conf >/dev/null
systemd-analyze cat-config /etc/systemd/system.conf >/dev/null
systemd-analyze cat-config systemd/system.conf systemd/journald.conf >/dev/null
systemd-analyze cat-config systemd/system.conf foo/bar systemd/journald.conf >/dev/null
systemd-analyze cat-config foo/bar
2023-04-15 21:33:02 +02:00
# security
systemd-analyze security
systemd-analyze security --json= off
systemd-analyze security --json= pretty | jq
systemd-analyze security --json= short | jq
2022-11-02 17:51:51 +01:00
2022-12-05 13:52:28 +01:00
if [ [ ! -v ASAN_OPTIONS ] ] ; then
# check that systemd-analyze cat-config paths work in a chroot
mkdir -p /tmp/root
mount --bind / /tmp/root
systemd-analyze cat-config systemd/system-preset >/tmp/out1
chroot /tmp/root systemd-analyze cat-config systemd/system-preset >/tmp/out2
diff /tmp/out{ 1,2}
fi
# verify
2021-08-25 09:44:26 -07:00
mkdir -p /tmp/img/usr/lib/systemd/system/
mkdir -p /tmp/img/opt/
touch /tmp/img/opt/script0.sh
chmod +x /tmp/img/opt/script0.sh
cat <<EOF >/tmp/img/usr/lib/systemd/system/testfile.service
[ Service]
ExecStart = /opt/script0.sh
EOF
set +e
# Default behaviour is to recurse through all dependencies when unit is loaded
2023-04-05 15:50:42 +02:00
( ! systemd-analyze verify --root= /tmp/img/ testfile.service)
2021-08-25 09:44:26 -07:00
# As above, recurses through all dependencies when unit is loaded
2023-04-05 15:50:42 +02:00
( ! systemd-analyze verify --recursive-errors= yes --root= /tmp/img/ testfile.service)
2021-08-25 09:44:26 -07:00
# Recurses through unit file and its direct dependencies when unit is loaded
2023-04-05 15:50:42 +02:00
( ! systemd-analyze verify --recursive-errors= one --root= /tmp/img/ testfile.service)
2021-08-25 09:44:26 -07:00
set -e
# zero exit status since dependencies are ignored when unit is loaded
systemd-analyze verify --recursive-errors= no --root= /tmp/img/ testfile.service
rm /tmp/img/usr/lib/systemd/system/testfile.service
cat <<EOF >/tmp/testfile.service
[ Unit]
foo = bar
[ Service]
ExecStart = echo hello
EOF
cat <<EOF >/tmp/testfile2.service
[ Unit]
Requires = testfile.service
[ Service]
ExecStart = echo hello
EOF
# Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded
systemd-analyze verify --recursive-errors= no /tmp/testfile2.service
set +e
2021-10-20 09:38:57 +02:00
# Non-zero exit status since all associated dependencies are recursively loaded when the unit file is loaded
2023-04-05 15:50:42 +02:00
( ! systemd-analyze verify --recursive-errors= yes /tmp/testfile2.service)
2021-08-25 09:44:26 -07:00
set -e
rm /tmp/testfile.service
rm /tmp/testfile2.service
cat <<EOF >/tmp/testfile.service
[ Service]
ExecStart = echo hello
2022-04-30 23:29:10 +01:00
DeviceAllow = /dev/sda
2021-08-25 09:44:26 -07:00
EOF
2021-09-28 23:52:39 -07:00
# Prevent regression from #13380 and #20859 where we can't verify hidden files
cp /tmp/testfile.service /tmp/.testfile.service
systemd-analyze verify /tmp/.testfile.service
rm /tmp/.testfile.service
2021-08-25 09:44:26 -07:00
2021-09-29 10:09:34 -04:00
# Alias a unit file's name on disk (see #20061)
cp /tmp/testfile.service /tmp/testsrvc
2023-04-05 15:50:42 +02:00
( ! systemd-analyze verify /tmp/testsrvc)
2021-09-29 10:09:34 -04:00
systemd-analyze verify /tmp/testsrvc:alias.service
2021-08-25 09:44:26 -07:00
# Zero exit status since the value used for comparison determine exposure to security threats is by default 100
systemd-analyze security --offline= true /tmp/testfile.service
#The overall exposure level assigned to the unit is greater than the set threshold
2023-04-05 15:50:42 +02:00
( ! systemd-analyze security --threshold= 90 --offline= true /tmp/testfile.service)
2021-08-25 09:44:26 -07:00
2022-04-30 23:29:10 +01:00
# Ensure we print the list of ACLs, see https://github.com/systemd/systemd/issues/23185
systemd-analyze security --offline= true /tmp/testfile.service | grep -q -F "/dev/sda"
2021-08-25 09:44:26 -07:00
rm /tmp/testfile.service
cat <<EOF >/tmp/img/usr/lib/systemd/system/testfile.service
[ Service]
ExecStart = echo hello
PrivateNetwork = yes
PrivateDevices = yes
PrivateUsers = yes
EOF
# The new overall exposure level assigned to the unit is less than the set thresholds
# Verifies that the --offline= option works with --root=
systemd-analyze security --threshold= 90 --offline= true --root= /tmp/img/ testfile.service
# Added an additional "INVALID_ID" id to the .json to verify that nothing breaks when input is malformed
# The PrivateNetwork id description and weight was changed to verify that 'security' is actually reading in
# values from the .json file when required. The default weight for "PrivateNetwork" is 2500, and the new weight
# assigned to that id in the .json file is 6000. This increased weight means that when the "PrivateNetwork" key is
# set to 'yes' (as above in the case of testfile.service) in the content of the unit file, the overall exposure
# level for the unit file should decrease to account for that increased weight.
cat <<EOF >/tmp/testfile.json
2021-11-04 19:22:28 +00:00
{ "UserOrDynamicUser" :
2021-08-25 09:44:26 -07:00
{ "description_bad" : "Service runs as root user" ,
2021-11-04 19:48:58 +00:00
"weight" : 0,
2021-08-25 09:44:26 -07:00
"range" : 10
} ,
"SupplementaryGroups" :
{ "description_good" : "Service has no supplementary groups" ,
"description_bad" : "Service runs with supplementary groups" ,
"description_na" : "Service runs as root, option does not matter" ,
"weight" : 200,
"range" : 1
} ,
"PrivateDevices" :
{ "description_good" : "Service has no access to hardware devices" ,
"description_bad" : "Service potentially has access to hardware devices" ,
"weight" : 1000,
"range" : 1
} ,
"PrivateMounts" :
{ "description_good" : "Service cannot install system mounts" ,
"description_bad" : "Service may install system mounts" ,
"weight" : 1000,
"range" : 1
} ,
"PrivateNetwork" :
{ "description_good" : "Service doesn't have access to the host's network" ,
"description_bad" : "Service has access to the host's network" ,
"weight" : 6000,
"range" : 1
} ,
"PrivateTmp" :
{ "description_good" : "Service has no access to other software's temporary files" ,
"description_bad" : "Service has access to other software's temporary files" ,
"weight" : 1000,
"range" : 1
} ,
"PrivateUsers" :
{ "description_good" : "Service does not have access to other users" ,
"description_bad" : "Service has access to other users" ,
"weight" : 1000,
"range" : 1
} ,
"ProtectControlGroups" :
{ "description_good" : "Service cannot modify the control group file system" ,
"description_bad" : "Service may modify the control group file system" ,
"weight" : 1000,
"range" : 1
} ,
"ProtectKernelModules" :
{ "description_good" : "Service cannot load or read kernel modules" ,
"description_bad" : "Service may load or read kernel modules" ,
"weight" : 1000,
"range" : 1
} ,
"ProtectKernelTunables" :
{ "description_good" : "Service cannot alter kernel tunables (/proc/sys, …)" ,
"description_bad" : "Service may alter kernel tunables" ,
"weight" : 1000,
"range" : 1
} ,
"ProtectKernelLogs" :
{ "description_good" : "Service cannot read from or write to the kernel log ring buffer" ,
"description_bad" : "Service may read from or write to the kernel log ring buffer" ,
"weight" : 1000,
"range" : 1
} ,
"ProtectClock" :
{ "description_good" : "Service cannot write to the hardware clock or system clock" ,
"description_bad" : "Service may write to the hardware clock or system clock" ,
"weight" : 1000,
"range" : 1
} ,
"ProtectHome" :
{ "weight" : 1000,
"range" : 10
} ,
"ProtectHostname" :
{ "description_good" : "Service cannot change system host/domainname" ,
"description_bad" : "Service may change system host/domainname" ,
"weight" : 50,
"range" : 1
} ,
"ProtectSystem" :
{ "weight" : 1000,
"range" : 10
} ,
2021-11-04 19:22:28 +00:00
"RootDirectoryOrRootImage" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Service has its own root directory/image" ,
"description_bad" : "Service runs within the host's root directory" ,
"weight" : 200,
"range" : 1
} ,
"LockPersonality" :
{ "description_good" : "Service cannot change ABI personality" ,
"description_bad" : "Service may change ABI personality" ,
"weight" : 100,
"range" : 1
} ,
"MemoryDenyWriteExecute" :
{ "description_good" : "Service cannot create writable executable memory mappings" ,
"description_bad" : "Service may create writable executable memory mappings" ,
"weight" : 100,
"range" : 1
} ,
"NoNewPrivileges" :
{ "description_good" : "Service processes cannot acquire new privileges" ,
"description_bad" : "Service processes may acquire new privileges" ,
"weight" : 1000,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_ADMIN" :
{ "description_good" : "Service has no administrator privileges" ,
"description_bad" : "Service has administrator privileges" ,
"weight" : 1500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SET_UID_GID_PCAP" :
{ "description_good" : "Service cannot change UID/GID identities/capabilities" ,
"description_bad" : "Service may change UID/GID identities/capabilities" ,
"weight" : 1500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_PTRACE" :
{ "description_good" : "Service has no ptrace() debugging abilities" ,
"description_bad" : "Service has ptrace() debugging abilities" ,
"weight" : 1500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_TIME" :
{ "description_good" : "Service processes cannot change the system clock" ,
"description_bad" : "Service processes may change the system clock" ,
"weight" : 1000,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_NET_ADMIN" :
{ "description_good" : "Service has no network configuration privileges" ,
"description_bad" : "Service has network configuration privileges" ,
"weight" : 1000,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_RAWIO" :
{ "description_good" : "Service has no raw I/O access" ,
"description_bad" : "Service has raw I/O access" ,
"weight" : 1000,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_MODULE" :
{ "description_good" : "Service cannot load kernel modules" ,
"description_bad" : "Service may load kernel modules" ,
"weight" : 1000,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_AUDIT" :
{ "description_good" : "Service has no audit subsystem access" ,
"description_bad" : "Service has audit subsystem access" ,
"weight" : 500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYSLOG" :
{ "description_good" : "Service has no access to kernel logging" ,
"description_bad" : "Service has access to kernel logging" ,
"weight" : 500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_NICE_RESOURCE" :
{ "description_good" : "Service has no privileges to change resource use parameters" ,
"description_bad" : "Service has privileges to change resource use parameters" ,
"weight" : 500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_MKNOD" :
{ "description_good" : "Service cannot create device nodes" ,
"description_bad" : "Service may create device nodes" ,
"weight" : 500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_CHOWN_FSETID_SETFCAP" :
{ "description_good" : "Service cannot change file ownership/access mode/capabilities" ,
"description_bad" : "Service may change file ownership/access mode/capabilities unrestricted" ,
"weight" : 1000,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_DAC_FOWNER_IPC_OWNER" :
{ "description_good" : "Service cannot override UNIX file/IPC permission checks" ,
"description_bad" : "Service may override UNIX file/IPC permission checks" ,
"weight" : 1000,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_KILL" :
{ "description_good" : "Service cannot send UNIX signals to arbitrary processes" ,
"description_bad" : "Service may send UNIX signals to arbitrary processes" ,
"weight" : 500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_NET_BIND_SERVICE_BROADCAST_RAW" :
{ "description_good" : "Service has no elevated networking privileges" ,
"description_bad" : "Service has elevated networking privileges" ,
"weight" : 500,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_BOOT" :
{ "description_good" : "Service cannot issue reboot()" ,
"description_bad" : "Service may issue reboot()" ,
"weight" : 100,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_MAC" :
{ "description_good" : "Service cannot adjust SMACK MAC" ,
"description_bad" : "Service may adjust SMACK MAC" ,
"weight" : 100,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_LINUX_IMMUTABLE" :
{ "description_good" : "Service cannot mark files immutable" ,
"description_bad" : "Service may mark files immutable" ,
"weight" : 75,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_IPC_LOCK" :
{ "description_good" : "Service cannot lock memory into RAM" ,
"description_bad" : "Service may lock memory into RAM" ,
"weight" : 50,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_CHROOT" :
{ "description_good" : "Service cannot issue chroot()" ,
"description_bad" : "Service may issue chroot()" ,
"weight" : 50,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_BLOCK_SUSPEND" :
{ "description_good" : "Service cannot establish wake locks" ,
"description_bad" : "Service may establish wake locks" ,
"weight" : 25,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_WAKE_ALARM" :
{ "description_good" : "Service cannot program timers that wake up the system" ,
"description_bad" : "Service may program timers that wake up the system" ,
"weight" : 25,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_LEASE" :
{ "description_good" : "Service cannot create file leases" ,
"description_bad" : "Service may create file leases" ,
"weight" : 25,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_TTY_CONFIG" :
{ "description_good" : "Service cannot issue vhangup()" ,
"description_bad" : "Service may issue vhangup()" ,
"weight" : 25,
"range" : 1
} ,
"CapabilityBoundingSet_CAP_SYS_PACCT" :
{ "description_good" : "Service cannot use acct()" ,
"description_bad" : "Service may use acct()" ,
"weight" : 25,
"range" : 1
} ,
"UMask" :
{ "weight" : 100,
"range" : 10
} ,
"KeyringMode" :
{ "description_good" : "Service doesn't share key material with other services" ,
"description_bad" : "Service shares key material with other service" ,
"weight" : 1000,
"range" : 1
} ,
"ProtectProc" :
{ "description_good" : "Service has restricted access to process tree(/proc hidepid=)" ,
"description_bad" : "Service has full access to process tree(/proc hidepid=)" ,
"weight" : 1000,
"range" : 3
} ,
"ProcSubset" :
{ "description_good" : "Service has no access to non-process/proc files(/proc subset=)" ,
"description_bad" : "Service has full access to non-process/proc files(/proc subset=)" ,
"weight" : 10,
"range" : 1
} ,
"NotifyAccess" :
{ "description_good" : "Service child processes cannot alter service state" ,
"description_bad" : "Service child processes may alter service state" ,
"weight" : 1000,
"range" : 1
} ,
"RemoveIPC" :
{ "description_good" : "Service user cannot leave SysV IPC objects around" ,
"description_bad" : "Service user may leave SysV IPC objects around" ,
"description_na" : "Service runs as root, option does not apply" ,
"weight" : 100,
"range" : 1
} ,
"Delegate" :
{ "description_good" : "Service does not maintain its own delegated control group subtree" ,
"description_bad" : "Service maintains its own delegated control group subtree" ,
"weight" : 100,
"range" : 1
} ,
"RestrictRealtime" :
{ "description_good" : "Service realtime scheduling access is restricted" ,
"description_bad" : "Service may acquire realtime scheduling" ,
"weight" : 500,
"range" : 1
} ,
"RestrictSUIDSGID" :
{ "description_good" : "SUID/SGIDfilecreationbyserviceisrestricted" ,
"description_bad" : "ServicemaycreateSUID/SGIDfiles" ,
"weight" : 1000,
"range" : 1
} ,
2021-09-06 11:33:16 -04:00
"RestrictNamespaces_user" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Servicecannotcreateusernamespaces" ,
"description_bad" : "Servicemaycreateusernamespaces" ,
"weight" : 1500,
"range" : 1
} ,
2021-09-06 11:33:16 -04:00
"RestrictNamespaces_mnt" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Service cannot create file system namespaces" ,
"description_bad" : "Service may create file system namespaces" ,
"weight" : 500,
"range" : 1
} ,
2021-09-06 11:33:16 -04:00
"RestrictNamespaces_ipc" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Service cannot create IPC namespaces" ,
"description_bad" : "Service may create IPC namespaces" ,
"weight" : 500,
"range" : 1
} ,
2021-09-06 11:33:16 -04:00
"RestrictNamespaces_pid" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Service cannot create process namespaces" ,
"description_bad" : "Service may create process namespaces" ,
"weight" : 500,
"range" : 1
} ,
2021-09-06 11:33:16 -04:00
"RestrictNamespaces_cgroup" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Service cannot create cgroup namespaces" ,
"description_bad" : "Service may create cgroup namespaces" ,
"weight" : 500,
"range" : 1
} ,
2021-09-06 11:33:16 -04:00
"RestrictNamespaces_net" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Service cannot create network namespaces" ,
"description_bad" : "Service may create network namespaces" ,
"weight" : 500,
"range" : 1
} ,
2021-09-06 11:33:16 -04:00
"RestrictNamespaces_uts" :
2021-08-25 09:44:26 -07:00
{ "description_good" : "Service cannot create hostname namespaces" ,
"description_bad" : "Service may create hostname namespaces" ,
"weight" : 100,
"range" : 1
} ,
"RestrictAddressFamilies_AF_INET_INET6" :
{ "description_good" : "Service cannot allocate Internet sockets" ,
"description_bad" : "Service may allocate Internet sockets" ,
"weight" : 1500,
"range" : 1
} ,
"RestrictAddressFamilies_AF_UNIX" :
{ "description_good" : "Service cannot allocate local sockets" ,
"description_bad" : "Service may allocate local sockets" ,
"weight" : 25,
"range" : 1
} ,
"RestrictAddressFamilies_AF_NETLINK" :
{ "description_good" : "Service cannot allocate netlink sockets" ,
"description_bad" : "Service may allocate netlink sockets" ,
"weight" : 200,
"range" : 1
} ,
"RestrictAddressFamilies_AF_PACKET" :
{ "description_good" : "Service cannot allocate packet sockets" ,
"description_bad" : "Service may allocate packet sockets" ,
"weight" : 1000,
"range" : 1
} ,
"RestrictAddressFamilies_OTHER" :
{ "description_good" : "Service cannot allocate exotic sockets" ,
"description_bad" : "Service may allocate exotic sockets" ,
"weight" : 1250,
"range" : 1
} ,
"SystemCallArchitectures" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_swap" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_obsolete" :
{ "weight" : 250,
"range" : 10
} ,
"SystemCallFilter_clock" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_cpu_emulation" :
{ "weight" : 250,
"range" : 10
} ,
"SystemCallFilter_debug" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_mount" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_module" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_raw_io" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_reboot" :
{ "weight" : 1000,
"range" : 10
} ,
"SystemCallFilter_privileged" :
{ "weight" : 700,
"range" : 10
} ,
"SystemCallFilter_resources" :
{ "weight" : 700,
"range" : 10
} ,
"IPAddressDeny" :
{ "weight" : 1000,
"range" : 10
} ,
"DeviceAllow" :
{ "weight" : 1000,
"range" : 10
} ,
"AmbientCapabilities" :
{ "description_good" : "Service process does not receive ambient capabilities" ,
"description_bad" : "Service process receives ambient capabilities" ,
"weight" : 500,
"range" : 1
} ,
"INVALID_ID" :
{ "weight" : 1000,
"range" : 10
}
}
EOF
# Reads in custom security requirements from the parsed .json file and uses these for comparison
systemd-analyze security --threshold= 90 --offline= true \
--security-policy= /tmp/testfile.json \
--root= /tmp/img/ testfile.service
2021-11-26 15:46:40 +00:00
# The strict profile adds a lot of sanboxing options
2022-04-01 00:53:29 +01:00
systemd-analyze security --threshold= 25 --offline= true \
2021-11-26 15:46:40 +00:00
--security-policy= /tmp/testfile.json \
--profile= strict \
--root= /tmp/img/ testfile.service
# The trusted profile doesn't add any sanboxing options
2023-04-05 15:50:42 +02:00
( ! systemd-analyze security --threshold= 25 --offline= true \
2021-11-26 15:46:40 +00:00
--security-policy= /tmp/testfile.json \
--profile= /usr/lib/systemd/portable/profile/trusted/service.conf \
2023-04-05 15:50:42 +02:00
--root= /tmp/img/ testfile.service)
2021-11-26 15:46:40 +00:00
2023-04-05 15:50:42 +02:00
( ! systemd-analyze security --threshold= 50 --offline= true \
2021-08-25 09:44:26 -07:00
--security-policy= /tmp/testfile.json \
2023-04-05 15:50:42 +02:00
--root= /tmp/img/ testfile.service)
2021-08-25 09:44:26 -07:00
rm /tmp/img/usr/lib/systemd/system/testfile.service
analyze: add inspect-elf verb to parse package metadata
Parses and prints package metadata from executables, libraries and core files
$ systemd-analyze inspect-elf /tmp/core ../fsverity-utils/fsverityb /bin/bash --json=off --no-pager
__________________________
path: /tmp/core
elfType: coredump
elfArchitecture: AMD x86-64
module name: /tmp/crash
type: deb
name: hello
version: 1.0
architecture: amd64
os: debian
osVersion: 11
buildId: b33541096a09c29a0ba4ec5c69364a2711b7c269
module name: /usr/lib/x86_64-linux-gnu/libc-2.31.so
type: deb
name: hello
version: 1.0
architecture: amd64
os: debian
osVersion: 11
buildId: 54eef5ce96cf37cb175b0d93186836ca1caf470c
module name: /usr/lib/x86_64-linux-gnu/ld-2.31.so
type: deb
name: hello
version: 1.0
architecture: amd64
os: debian
osVersion: 11
buildId: 32438eb3b034da54caf58c7a65446639f7cfe274
__________________________________________________________________
path: /home/luca/git/systemd/../fsverity-utils/fsverity
elfType: executable
elfArchitecture: AMD x86-64
type: deb
name: fsverity-utils
version: 1.3-1
architecture: amd64
os: debian
debugInfoUrl: https://debuginfod.debian.net
buildId: 05b899e6ee0d3653e20458719b202ed3ca8d566f
_________________________
path: /bin/bash
elfType: executable
elfArchitecture: AMD x86-64
buildId: 4fef260f60e257d2dbd4126bf8add83837aea190
$
$ systemd-analyze inspect-elf /tmp/core ../fsverity-utils/fsverity /bin/bash /tmp/core.test-condition.1000.f9b9a84a9fd1482c9702d6afa6f6934b.37640.1637083078000000 --json=pretty --no-pager
{
"elfType" : "coredump",
"elfArchitecture" : "AMD x86-64",
"/home/bluca/git/fsverity-utils/fsverity" : {
"type" : "deb",
"name" : "fsverity-utils",
"version" : "1.3-1",
"buildId" : "7c895ecd2a271f93e96268f479fdc3c64a2ec4ee"
},
"/home/bluca/git/fsverity-utils/libfsverity.so.0" : {
"type" : "deb",
"name" : "fsverity-utils",
"version" : "1.3-1",
"buildId" : "b5e428254abf14237b0ae70ed85fffbb98a78f88"
}
}
{
"elfType" : "executable",
"elfArchitecture" : "AMD x86-64",
"/home/bluca/git/systemd/../fsverity-utils/fsverity" : {
"type" : "deb",
"name" : "fsverity-utils",
"version" : "1.3-1",
"buildId" : "7c895ecd2a271f93e96268f479fdc3c64a2ec4ee"
}
}
{
"elfType" : "executable",
"elfArchitecture" : "AMD x86-64",
"/bin/bash" : {
"buildId" : "3313b4cb119dcce16927a9b6cc61dcd97dfc4d59"
}
}
{
"elfType" : "coredump",
"elfArchitecture" : "AMD x86-64"
}
2021-11-17 01:45:07 +00:00
if systemd-analyze --version | grep -q -F "+ELFUTILS" ; then
systemd-analyze inspect-elf --json= short /lib/systemd/systemd | grep -q -F '"elfType":"executable"'
fi
2022-04-29 23:50:11 +01:00
systemd-analyze --threshold= 90 security systemd-journald.service
2022-06-16 03:21:28 +09:00
# issue 23663
check( ) { (
set +x
output = $( systemd-analyze security --offline= " ${ 2 ? } " " ${ 3 ? } " | grep -F 'SystemCallFilter=' )
assert_in " System call ${ 1 ? } list " " $output "
assert_in "[+✓] SystemCallFilter=~@swap" " $output "
assert_in "[+✓] SystemCallFilter=~@resources" " $output "
assert_in "[+✓] SystemCallFilter=~@reboot" " $output "
assert_in "[+✓] SystemCallFilter=~@raw-io" " $output "
assert_in "[-✗] SystemCallFilter=~@privileged" " $output "
assert_in "[+✓] SystemCallFilter=~@obsolete" " $output "
assert_in "[+✓] SystemCallFilter=~@mount" " $output "
assert_in "[+✓] SystemCallFilter=~@module" " $output "
assert_in "[+✓] SystemCallFilter=~@debug" " $output "
assert_in "[+✓] SystemCallFilter=~@cpu-emulation" " $output "
assert_in "[-✗] SystemCallFilter=~@clock" " $output "
) }
export -n SYSTEMD_LOG_LEVEL
mkdir -p /run/systemd/system
cat >/run/systemd/system/allow-list.service <<EOF
[ Service]
ExecStart = false
SystemCallFilter = @system-service
SystemCallFilter = ~@resources:ENOANO @privileged
SystemCallFilter = @clock
EOF
cat >/run/systemd/system/deny-list.service <<EOF
[ Service]
ExecStart = false
SystemCallFilter = ~@known
SystemCallFilter = @system-service
SystemCallFilter = ~@resources:ENOANO @privileged
SystemCallFilter = @clock
EOF
systemctl daemon-reload
check allow yes /run/systemd/system/allow-list.service
check allow no allow-list.service
check deny yes /run/systemd/system/deny-list.service
check deny no deny-list.service
output = $( systemd-run -p "SystemCallFilter=@system-service" -p "SystemCallFilter=~@resources:ENOANO @privileged" -p "SystemCallFilter=@clock" sleep 60 2>& 1)
name = $( echo " $output " | awk '{ print $4 }' )
check allow yes /run/systemd/transient/" $name "
check allow no " $name "
output = $( systemd-run -p "SystemCallFilter=~@known" -p "SystemCallFilter=@system-service" -p "SystemCallFilter=~@resources:ENOANO @privileged" -p "SystemCallFilter=@clock" sleep 60 2>& 1)
name = $( echo " $output " | awk '{ print $4 }' )
check deny yes /run/systemd/transient/" $name "
check deny no " $name "
2022-12-06 21:15:06 +01:00
# Let's also test the "image-policy" verb
systemd-analyze image-policy '*' 2>& 1 | grep -q -F "Long form: =verity+signed+encrypted+unprotected+unused+absent"
systemd-analyze image-policy '-' 2>& 1 | grep -q -F "Long form: =unused+absent"
systemd-analyze image-policy 'home=encrypted:usr=verity' 2>& 1 | grep -q -F "Long form: usr=verity:home=encrypted:=unused+absent"
systemd-analyze image-policy 'home=encrypted:usr=verity' 2>& 1 | grep -q -e '^home \+encrypted \+'
systemd-analyze image-policy 'home=encrypted:usr=verity' 2>& 1 | grep -q -e '^usr \+verity \+'
systemd-analyze image-policy 'home=encrypted:usr=verity' 2>& 1 | grep -q -e '^root \+ignore \+'
systemd-analyze image-policy 'home=encrypted:usr=verity' 2>& 1 | grep -q -e '^usr-verity \+unprotected \+'
2023-04-05 15:50:42 +02:00
( ! systemd-analyze image-policy 'doedel' )
2022-12-06 21:15:06 +01:00
2023-06-27 18:45:34 +02:00
# Output is very hard to predict, but let's run it for coverage anyway
systemd-analyze pcrs
systemd-analyze pcrs --json= pretty
systemd-analyze pcrs 14 7 0 ima
2021-08-25 09:44:26 -07:00
systemd-analyze log-level info
echo OK >/testok
exit 0