# shellcheck disable=SC2016
set -eux
-# shellcheck source=test/units/assert.sh
-. "$(dirname "$0")"/assert.sh
+# shellcheck source=test/units/util.sh
+. "$(dirname "$0")"/util.sh
systemctl log-level debug
export SYSTEMD_LOG_LEVEL=debug
# Sanity checks
#
-# We can't really test time, blame, critical-chain and plot verbs here, as
+# We can't really test time, critical-chain and plot verbs here, as
# the testsuite service is a part of the boot transaction, so let's assume
# they fail
systemd-analyze || :
systemd-analyze time || :
-systemd-analyze blame || :
systemd-analyze critical-chain || :
+# blame
+systemd-analyze blame
+systemd-run --wait --user --pipe -M testuser@.host systemd-analyze blame
# plot
systemd-analyze plot >/dev/null || :
systemd-analyze plot --json=pretty >/dev/null || :
systemd-analyze dot "systemd-*.service" >/dev/null
(! systemd-analyze dot systemd-journald.service systemd-logind.service "*" bbb ccc)
# dump
+# 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
systemd-analyze dump >/dev/null
systemd-analyze dump "*" >/dev/null
systemd-analyze dump "*.socket" >/dev/null
systemd-analyze dump "*.socket" "*.service" aaaaaaa ... >/dev/null
systemd-analyze dump systemd-journald.service >/dev/null
+systemd-analyze malloc >/dev/null
(! systemd-analyze dump "")
# unit-files
systemd-analyze unit-files >/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
+systemd-analyze cat-config --tldr systemd/system.conf >/dev/null
+systemd-analyze cat-config --tldr /etc/systemd/system.conf >/dev/null
+systemd-analyze cat-config --tldr systemd/system.conf systemd/journald.conf >/dev/null
+systemd-analyze cat-config --tldr systemd/system.conf foo/bar systemd/journald.conf >/dev/null
+systemd-analyze cat-config --tldr foo/bar
+# security
+systemd-analyze security
+systemd-analyze security --json=off
+systemd-analyze security --json=pretty | jq
+systemd-analyze security --json=short | jq
if [[ ! -v ASAN_OPTIONS ]]; then
# check that systemd-analyze cat-config paths work in a chroot
mkdir -p /tmp/root
mount --bind / /tmp/root
+ if mountpoint -q /usr; then
+ mount --bind /usr /tmp/root/usr
+ fi
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}
set +e
# Default behaviour is to recurse through all dependencies when unit is loaded
-systemd-analyze verify --root=/tmp/img/ testfile.service \
- && { echo 'unexpected success'; exit 1; }
+(! systemd-analyze verify --root=/tmp/img/ testfile.service)
# As above, recurses through all dependencies when unit is loaded
-systemd-analyze verify --recursive-errors=yes --root=/tmp/img/ testfile.service \
- && { echo 'unexpected success'; exit 1; }
+(! systemd-analyze verify --recursive-errors=yes --root=/tmp/img/ testfile.service)
# Recurses through unit file and its direct dependencies when unit is loaded
-systemd-analyze verify --recursive-errors=one --root=/tmp/img/ testfile.service \
- && { echo 'unexpected success'; exit 1; }
+(! systemd-analyze verify --recursive-errors=one --root=/tmp/img/ testfile.service)
set -e
set +e
# Non-zero exit status since all associated dependencies are recursively loaded when the unit file is loaded
-systemd-analyze verify --recursive-errors=yes /tmp/testfile2.service \
- && { echo 'unexpected success'; exit 1; }
+(! systemd-analyze verify --recursive-errors=yes /tmp/testfile2.service)
set -e
rm /tmp/testfile.service
rm /tmp/testfile2.service
+cat <<EOF >/tmp/sample.service
+[Unit]
+Description = A Sample Service
+
+[Service]
+ExecStart = echo hello
+Slice=support.slice
+EOF
+
+# Zero exit status since no additional dependencies are recursively loaded when the unit file is loaded
+systemd-analyze verify --recursive-errors=no /tmp/sample.service
+
cat <<EOF >/tmp/testfile.service
[Service]
ExecStart = echo hello
# Alias a unit file's name on disk (see #20061)
cp /tmp/testfile.service /tmp/testsrvc
-systemd-analyze verify /tmp/testsrvc \
- && { echo 'unexpected success'; exit 1; }
+(! systemd-analyze verify /tmp/testsrvc)
systemd-analyze verify /tmp/testsrvc:alias.service
# 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
-set +e
#The overall exposure level assigned to the unit is greater than the set threshold
-systemd-analyze security --threshold=90 --offline=true /tmp/testfile.service \
- && { echo 'unexpected success'; exit 1; }
-set -e
+(! systemd-analyze security --threshold=90 --offline=true /tmp/testfile.service)
# 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"
# Verifies that the --offline= option works with --root=
systemd-analyze security --threshold=90 --offline=true --root=/tmp/img/ testfile.service
+cat <<EOF >/tmp/foo@.service
+[Service]
+ExecStart=ls
+EOF
+
+cat <<EOF >/tmp/hoge@test.service
+[Service]
+ExecStart=ls
+EOF
+
+# issue #30357
+pushd /tmp
+systemd-analyze verify foo@bar.service
+systemd-analyze verify foo@.service
+systemd-analyze verify hoge@test.service
+(! systemd-analyze verify hoge@nonexist.service)
+(! systemd-analyze verify hoge@.service)
+popd
+pushd /
+systemd-analyze verify tmp/foo@bar.service
+systemd-analyze verify tmp/foo@.service
+systemd-analyze verify tmp/hoge@test.service
+(! systemd-analyze verify tmp/hoge@nonexist.service)
+(! systemd-analyze verify tmp/hoge@.service)
+popd
+pushd /usr
+systemd-analyze verify ../tmp/foo@bar.service
+systemd-analyze verify ../tmp/foo@.service
+systemd-analyze verify ../tmp/hoge@test.service
+(! systemd-analyze verify ../tmp/hoge@nonexist.service)
+(! systemd-analyze verify ../tmp/hoge@.service)
+popd
+systemd-analyze verify /tmp/foo@bar.service
+systemd-analyze verify /tmp/foo@.service
+systemd-analyze verify /tmp/hoge@test.service
+(! systemd-analyze verify /tmp/hoge@nonexist.service)
+(! systemd-analyze verify /tmp/hoge@.service)
+
+# test that all commands are verified.
+cat <<EOF >/tmp/multi-exec-start.service
+[Service]
+Type=oneshot
+ExecStart=true
+ExecStart=ls
+EOF
+systemd-analyze verify /tmp/multi-exec-start.service
+echo 'ExecStart=command-should-not-exist' >>/tmp/multi-exec-start.service
+(! systemd-analyze verify /tmp/multi-exec-start.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
"weight": 25,
"range": 1
},
+"CapabilityBoundingSet_CAP_BPF":
+ {"description_good": "Service may load BPF programs",
+ "description_bad": "Service may not load BPF programs",
+ "weight": 25,
+ "range": 1
+ },
"UMask":
{"weight": 100,
"range": 10
--profile=strict \
--root=/tmp/img/ testfile.service
-set +e
# The trusted profile doesn't add any sanboxing options
-systemd-analyze security --threshold=25 --offline=true \
+(! systemd-analyze security --threshold=25 --offline=true \
--security-policy=/tmp/testfile.json \
--profile=/usr/lib/systemd/portable/profile/trusted/service.conf \
- --root=/tmp/img/ testfile.service \
- && { echo 'unexpected success'; exit 1; }
+ --root=/tmp/img/ testfile.service)
-systemd-analyze security --threshold=50 --offline=true \
+(! systemd-analyze security --threshold=50 --offline=true \
--security-policy=/tmp/testfile.json \
- --root=/tmp/img/ testfile.service \
- && { echo 'unexpected success'; exit 1; }
-set -e
+ --root=/tmp/img/ testfile.service)
rm /tmp/img/usr/lib/systemd/system/testfile.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 }')
+name=$(echo "$output" | awk '{ print $4 }' | cut -d';' -f1)
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 }')
+name=$(echo "$output" | awk '{ print $4 }' | cut -d';' -f1)
check deny yes /run/systemd/transient/"$name"
check deny no "$name"
-systemd-analyze log-level info
+# 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 \+'
-echo OK >/testok
+(! systemd-analyze image-policy 'doedel')
+
+# 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
+
+systemd-analyze architectures
+systemd-analyze architectures --json=pretty
+systemd-analyze architectures x86
+systemd-analyze architectures x86-64
+systemd-analyze architectures native
+systemd-analyze architectures uname
+
+systemd-analyze log-level info
-exit 0
+touch /testok