2021-08-25 16:44:26 +00:00
|
|
|
#!/usr/bin/env bash
|
2021-10-17 16:13:06 +00:00
|
|
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
2021-08-25 16:44:26 +00:00
|
|
|
# shellcheck disable=SC2016
|
|
|
|
set -eux
|
|
|
|
|
2022-06-15 18:21:28 +00:00
|
|
|
# shellcheck source=test/units/assert.sh
|
|
|
|
. "$(dirname "$0")"/assert.sh
|
|
|
|
|
2021-08-25 16:44:26 +00:00
|
|
|
systemd-analyze log-level debug
|
2021-11-30 23:49:58 +00:00
|
|
|
export SYSTEMD_LOG_LEVEL=debug
|
2021-08-25 16:44:26 +00: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
|
|
|
|
systemd-analyze verify --root=/tmp/img/ testfile.service \
|
|
|
|
&& { echo 'unexpected success'; exit 1; }
|
|
|
|
|
|
|
|
# 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; }
|
|
|
|
|
|
|
|
# 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; }
|
|
|
|
|
|
|
|
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 07:38:57 +00:00
|
|
|
# Non-zero exit status since all associated dependencies are recursively loaded when the unit file is loaded
|
2021-08-25 16:44:26 +00:00
|
|
|
systemd-analyze verify --recursive-errors=yes /tmp/testfile2.service \
|
|
|
|
&& { echo 'unexpected success'; exit 1; }
|
|
|
|
set -e
|
|
|
|
|
|
|
|
rm /tmp/testfile.service
|
|
|
|
rm /tmp/testfile2.service
|
|
|
|
|
|
|
|
cat <<EOF >/tmp/testfile.service
|
|
|
|
[Service]
|
|
|
|
ExecStart = echo hello
|
2022-04-30 22:29:10 +00:00
|
|
|
DeviceAllow=/dev/sda
|
2021-08-25 16:44:26 +00:00
|
|
|
EOF
|
|
|
|
|
2021-09-29 06:52:39 +00: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 16:44:26 +00:00
|
|
|
|
2021-09-29 14:09:34 +00:00
|
|
|
# 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:alias.service
|
|
|
|
|
2021-08-25 16:44:26 +00: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
|
|
|
|
|
|
|
|
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
|
|
|
|
|
2022-04-30 22:29:10 +00: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 16:44:26 +00: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 16:44:26 +00:00
|
|
|
{"description_bad": "Service runs as root user",
|
2021-11-04 19:48:58 +00:00
|
|
|
"weight": 0,
|
2021-08-25 16:44:26 +00: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 16:44:26 +00: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 15:33:16 +00:00
|
|
|
"RestrictNamespaces_user":
|
2021-08-25 16:44:26 +00:00
|
|
|
{"description_good": "Servicecannotcreateusernamespaces",
|
|
|
|
"description_bad": "Servicemaycreateusernamespaces",
|
|
|
|
"weight": 1500,
|
|
|
|
"range": 1
|
|
|
|
},
|
2021-09-06 15:33:16 +00:00
|
|
|
"RestrictNamespaces_mnt":
|
2021-08-25 16:44:26 +00:00
|
|
|
{"description_good": "Service cannot create file system namespaces",
|
|
|
|
"description_bad": "Service may create file system namespaces",
|
|
|
|
"weight": 500,
|
|
|
|
"range": 1
|
|
|
|
},
|
2021-09-06 15:33:16 +00:00
|
|
|
"RestrictNamespaces_ipc":
|
2021-08-25 16:44:26 +00:00
|
|
|
{"description_good": "Service cannot create IPC namespaces",
|
|
|
|
"description_bad": "Service may create IPC namespaces",
|
|
|
|
"weight": 500,
|
|
|
|
"range": 1
|
|
|
|
},
|
2021-09-06 15:33:16 +00:00
|
|
|
"RestrictNamespaces_pid":
|
2021-08-25 16:44:26 +00:00
|
|
|
{"description_good": "Service cannot create process namespaces",
|
|
|
|
"description_bad": "Service may create process namespaces",
|
|
|
|
"weight": 500,
|
|
|
|
"range": 1
|
|
|
|
},
|
2021-09-06 15:33:16 +00:00
|
|
|
"RestrictNamespaces_cgroup":
|
2021-08-25 16:44:26 +00:00
|
|
|
{"description_good": "Service cannot create cgroup namespaces",
|
|
|
|
"description_bad": "Service may create cgroup namespaces",
|
|
|
|
"weight": 500,
|
|
|
|
"range": 1
|
|
|
|
},
|
2021-09-06 15:33:16 +00:00
|
|
|
"RestrictNamespaces_net":
|
2021-08-25 16:44:26 +00:00
|
|
|
{"description_good": "Service cannot create network namespaces",
|
|
|
|
"description_bad": "Service may create network namespaces",
|
|
|
|
"weight": 500,
|
|
|
|
"range": 1
|
|
|
|
},
|
2021-09-06 15:33:16 +00:00
|
|
|
"RestrictNamespaces_uts":
|
2021-08-25 16:44:26 +00: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-03-31 23:53:29 +00: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
|
|
|
|
|
2021-08-25 16:44:26 +00:00
|
|
|
set +e
|
2021-11-26 15:46:40 +00:00
|
|
|
# The trusted profile doesn't add any sanboxing options
|
2022-03-31 23:53:29 +00: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 \
|
|
|
|
--root=/tmp/img/ testfile.service \
|
|
|
|
&& { echo 'unexpected success'; exit 1; }
|
|
|
|
|
2021-08-25 16:44:26 +00:00
|
|
|
systemd-analyze security --threshold=50 --offline=true \
|
|
|
|
--security-policy=/tmp/testfile.json \
|
|
|
|
--root=/tmp/img/ testfile.service \
|
|
|
|
&& { echo 'unexpected success'; exit 1; }
|
|
|
|
set -e
|
|
|
|
|
|
|
|
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 22:50:11 +00:00
|
|
|
systemd-analyze --threshold=90 security systemd-journald.service
|
|
|
|
|
2022-06-15 18:21:28 +00: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"
|
|
|
|
|
2021-08-25 16:44:26 +00:00
|
|
|
systemd-analyze log-level info
|
|
|
|
|
|
|
|
echo OK >/testok
|
|
|
|
|
|
|
|
exit 0
|