mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-18 06:03:42 +03:00
Merge pull request #20525 from maanyagoenka/custom-security
systemd-analyze: add option to enable users to custom define security requirements in the form of a .json file
This commit is contained in:
commit
cc3001693d
@ -792,6 +792,323 @@ Service b@0.service not loaded, b.socket cannot be started.
|
||||
as well and its default value is 100.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--security-policy=<replaceable>PATH</replaceable></option></term>
|
||||
|
||||
<listitem><para>With <command>security</command>, allow the user to define a custom set of
|
||||
requirements formatted as a JSON file against which to compare the specified unit file(s)
|
||||
and determine their overall exposure level to security threats.</para>
|
||||
|
||||
<table>
|
||||
<title>Accepted Assessment Test Identifiers</title>
|
||||
|
||||
<tgroup cols='1'>
|
||||
<colspec colname='directive' />
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Assessment Test Identifier</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>UserOrDynamicUser</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SupplementaryGroups</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>PrivateMounts</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>PrivateDevices</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>PrivateTmp</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>PrivateNetwork</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>PrivateUsers</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectControlGroups</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectKernelModules</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectKernelTunables</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectKernelLogs</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectClock</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectHome</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectHostname</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectSystem</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RootDirectoryOrRootImage</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>LockPersonality</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>MemoryDenyWriteExecute</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>NoNewPrivileges</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_ADMIN</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SET_UID_GID_PCAP</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_PTRACE</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_TIME</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_NET_ADMIN</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_RAWIO</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_MODULE</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_AUDIT</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYSLOG</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_NICE_RESOURCE</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_MKNOD</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_CHOWN_FSETID_SETFCAP</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_DAC_FOWNER_IPC_OWNER</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_KILL</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_NET_BIND_SERVICE_BROADCAST_RAW</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_BOOT</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_MAC</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_LINUX_IMMUTABLE</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_IPC_LOCK</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_CHROOT</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_BLOCK_SUSPEND</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_WAKE_ALARM</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_LEASE</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>CapabilityBoundingSet_CAP_SYS_TTY_CONFIG</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>UMask</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>KeyringMode</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProtectProc</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ProcSubset</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>NotifyAccess</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RemoveIPC</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Delegate</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictRealtime</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictSUIDSGID</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictNamespaces_CLONE_NEWUSER</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictNamespaces_CLONE_NEWNS</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictNamespaces_CLONE_NEWIPC</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictNamespaces_CLONE_NEWPID</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictNamespaces_CLONE_NEWCGROUP</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictNamespaces_CLONE_NEWUTS</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictNamespaces_CLONE_NEWNET</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictAddressFamilies_AF_INET_INET6</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictAddressFamilies_AF_UNIX</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictAddressFamilies_AF_NETLINK</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictAddressFamilies_AF_PACKET</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>RestrictAddressFamilies_OTHER</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallArchitectures</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_swap</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_obsolete</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_clock</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_cpu_emulation</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_debug</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_mount</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_module</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_raw_io</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_reboot</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_privileged</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>SystemCallFilter_resources</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>IPAddressDeny</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>DeviceAllow</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>AmbientCapabilities</entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
<example>
|
||||
<title>JSON Policy</title>
|
||||
<para>The JSON file passed as a path parameter to <option>--security-policy=</option>
|
||||
has a top-level JSON object, with keys being the assessment test identifiers mentioned
|
||||
above. The values in the file should be JSON objects with one or more of the
|
||||
following fields: description_na (string), description_good (string), description_bad
|
||||
(string), weight (unsigned integer), and range (unsigned integer). If any of these fields
|
||||
corresponding to a specific id of the unit file is missing from the JSON object, the
|
||||
default built-in field value corresponding to that same id is used for security analysis
|
||||
as default. The weight and range fields are used in determining the overall exposure level
|
||||
of the unit files so by allowing users to manipulate these fields, 'security' gives them
|
||||
the option to decide for themself which ids are more important and hence, should have a greater
|
||||
effect on the exposure level. </para>
|
||||
|
||||
<programlisting>
|
||||
{
|
||||
"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 has no access to the host's network",
|
||||
"description_bad": "Service has access to the host's network",
|
||||
"weight": 2500,
|
||||
"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
|
||||
}
|
||||
}
|
||||
</programlisting>
|
||||
</example>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--iterations=<replaceable>NUMBER</replaceable></option></term>
|
||||
|
||||
|
@ -144,7 +144,7 @@ _systemd_analyze() {
|
||||
|
||||
elif __contains_word "$verb" ${VERBS[SECURITY]}; then
|
||||
if [[ $cur = -* ]]; then
|
||||
comps='--help --version --no-pager --system --user -H --host -M --machine --offline --threshold'
|
||||
comps='--help --version --no-pager --system --user -H --host -M --machine --offline --threshold --security-policy'
|
||||
else
|
||||
if __contains_word "--user" ${COMP_WORDS[*]}; then
|
||||
mode=--user
|
||||
|
@ -92,6 +92,7 @@ _arguments \
|
||||
'--recursive-errors=[When verifying a unit, control dependency verification]:MODE' \
|
||||
'--offline=[Perform a security review of the specified unit file(s)]:BOOL' \
|
||||
'--threshold=[Set a value to compare the overall security exposure level with]: NUMBER' \
|
||||
'--security-policy=[Allow user to use customized requirements to compare unit file(s) against]: PATH' \
|
||||
'--no-pager[Do not pipe output into a pager]' \
|
||||
'--man=[Do (not) check for existence of man pages]:boolean:(1 0)' \
|
||||
'--order[When generating graph for dot, show only order]' \
|
||||
|
@ -107,6 +107,7 @@ typedef struct SecurityInfo {
|
||||
|
||||
struct security_assessor {
|
||||
const char *id;
|
||||
const char *json_field;
|
||||
const char *description_good;
|
||||
const char *description_bad;
|
||||
const char *description_na;
|
||||
@ -754,6 +755,7 @@ static int assess_ambient_capabilities(
|
||||
static const struct security_assessor security_assessor_table[] = {
|
||||
{
|
||||
.id = "User=/DynamicUser=",
|
||||
.json_field = "UserOrDynamicUser",
|
||||
.description_bad = "Service runs as root user",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=",
|
||||
.weight = 2000,
|
||||
@ -762,6 +764,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SupplementaryGroups=",
|
||||
.json_field = "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",
|
||||
@ -772,6 +775,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "PrivateDevices=",
|
||||
.json_field = "PrivateDevices",
|
||||
.description_good = "Service has no access to hardware devices",
|
||||
.description_bad = "Service potentially has access to hardware devices",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices=",
|
||||
@ -782,6 +786,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "PrivateMounts=",
|
||||
.json_field = "PrivateMounts",
|
||||
.description_good = "Service cannot install system mounts",
|
||||
.description_bad = "Service may install system mounts",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateMounts=",
|
||||
@ -792,6 +797,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "PrivateNetwork=",
|
||||
.json_field = "PrivateNetwork",
|
||||
.description_good = "Service has no access to the host's network",
|
||||
.description_bad = "Service has access to the host's network",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateNetwork=",
|
||||
@ -802,6 +808,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "PrivateTmp=",
|
||||
.json_field = "PrivateTmp",
|
||||
.description_good = "Service has no access to other software's temporary files",
|
||||
.description_bad = "Service has access to other software's temporary files",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=",
|
||||
@ -813,6 +820,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "PrivateUsers=",
|
||||
.json_field = "PrivateUsers",
|
||||
.description_good = "Service does not have access to other users",
|
||||
.description_bad = "Service has access to other users",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateUsers=",
|
||||
@ -823,6 +831,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectControlGroups=",
|
||||
.json_field = "ProtectControlGroups",
|
||||
.description_good = "Service cannot modify the control group file system",
|
||||
.description_bad = "Service may modify the control group file system",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectControlGroups=",
|
||||
@ -833,6 +842,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectKernelModules=",
|
||||
.json_field = "ProtectKernelModules",
|
||||
.description_good = "Service cannot load or read kernel modules",
|
||||
.description_bad = "Service may load or read kernel modules",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelModules=",
|
||||
@ -843,6 +853,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectKernelTunables=",
|
||||
.json_field = "ProtectKernelTunables",
|
||||
.description_good = "Service cannot alter kernel tunables (/proc/sys, …)",
|
||||
.description_bad = "Service may alter kernel tunables",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelTunables=",
|
||||
@ -853,6 +864,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectKernelLogs=",
|
||||
.json_field = "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",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelLogs=",
|
||||
@ -863,6 +875,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectClock=",
|
||||
.json_field = "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",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectClock=",
|
||||
@ -873,6 +886,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectHome=",
|
||||
.json_field = "ProtectHome",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -881,6 +895,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectHostname=",
|
||||
.json_field = "ProtectHostname",
|
||||
.description_good = "Service cannot change system host/domainname",
|
||||
.description_bad = "Service may change system host/domainname",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHostname=",
|
||||
@ -891,6 +906,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectSystem=",
|
||||
.json_field = "ProtectSystem",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -899,6 +915,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RootDirectory=/RootImage=",
|
||||
.json_field = "RootDirectoryOrRootImage",
|
||||
.description_good = "Service has its own root directory/image",
|
||||
.description_bad = "Service runs within the host's root directory",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootDirectory=",
|
||||
@ -909,6 +926,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "LockPersonality=",
|
||||
.json_field = "LockPersonality",
|
||||
.description_good = "Service cannot change ABI personality",
|
||||
.description_bad = "Service may change ABI personality",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LockPersonality=",
|
||||
@ -919,6 +937,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "MemoryDenyWriteExecute=",
|
||||
.json_field = "MemoryDenyWriteExecute",
|
||||
.description_good = "Service cannot create writable executable memory mappings",
|
||||
.description_bad = "Service may create writable executable memory mappings",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#MemoryDenyWriteExecute=",
|
||||
@ -929,6 +948,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "NoNewPrivileges=",
|
||||
.json_field = "NoNewPrivileges",
|
||||
.description_good = "Service processes cannot acquire new privileges",
|
||||
.description_bad = "Service processes may acquire new privileges",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges=",
|
||||
@ -939,6 +959,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_ADMIN",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_ADMIN",
|
||||
.description_good = "Service has no administrator privileges",
|
||||
.description_bad = "Service has administrator privileges",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -949,6 +970,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP)",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SET_UID_GID_PCAP",
|
||||
.description_good = "Service cannot change UID/GID identities/capabilities",
|
||||
.description_bad = "Service may change UID/GID identities/capabilities",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -961,6 +983,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_PTRACE",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_PTRACE",
|
||||
.description_good = "Service has no ptrace() debugging abilities",
|
||||
.description_bad = "Service has ptrace() debugging abilities",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -971,6 +994,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_TIME",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_TIME",
|
||||
.description_good = "Service processes cannot change the system clock",
|
||||
.description_bad = "Service processes may change the system clock",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -981,6 +1005,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_NET_ADMIN",
|
||||
.json_field = "CapabilityBoundingSet_CAP_NET_ADMIN",
|
||||
.description_good = "Service has no network configuration privileges",
|
||||
.description_bad = "Service has network configuration privileges",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -991,6 +1016,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_RAWIO",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_RAWIO",
|
||||
.description_good = "Service has no raw I/O access",
|
||||
.description_bad = "Service has raw I/O access",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1001,6 +1027,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_MODULE",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_MODULE",
|
||||
.description_good = "Service cannot load kernel modules",
|
||||
.description_bad = "Service may load kernel modules",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1011,6 +1038,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_AUDIT_*",
|
||||
.json_field = "CapabilityBoundingSet_CAP_AUDIT",
|
||||
.description_good = "Service has no audit subsystem access",
|
||||
.description_bad = "Service has audit subsystem access",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1023,6 +1051,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYSLOG",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYSLOG",
|
||||
.description_good = "Service has no access to kernel logging",
|
||||
.description_bad = "Service has access to kernel logging",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1033,6 +1062,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE)",
|
||||
.json_field = "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",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1044,6 +1074,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_MKNOD",
|
||||
.json_field = "CapabilityBoundingSet_CAP_MKNOD",
|
||||
.description_good = "Service cannot create device nodes",
|
||||
.description_bad = "Service may create device nodes",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1054,6 +1085,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP)",
|
||||
.json_field = "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",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1066,6 +1098,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)",
|
||||
.json_field = "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",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1079,6 +1112,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_KILL",
|
||||
.json_field = "CapabilityBoundingSet_CAP_KILL",
|
||||
.description_good = "Service cannot send UNIX signals to arbitrary processes",
|
||||
.description_bad = "Service may send UNIX signals to arbitrary processes",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1089,6 +1123,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW)",
|
||||
.json_field = "CapabilityBoundingSet_CAP_NET_BIND_SERVICE_BROADCAST_RAW)",
|
||||
.description_good = "Service has no elevated networking privileges",
|
||||
.description_bad = "Service has elevated networking privileges",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1101,6 +1136,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_BOOT",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_BOOT",
|
||||
.description_good = "Service cannot issue reboot()",
|
||||
.description_bad = "Service may issue reboot()",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1111,6 +1147,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_MAC_*",
|
||||
.json_field = "CapabilityBoundingSet_CAP_MAC",
|
||||
.description_good = "Service cannot adjust SMACK MAC",
|
||||
.description_bad = "Service may adjust SMACK MAC",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1122,6 +1159,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE",
|
||||
.json_field = "CapabilityBoundingSet_CAP_LINUX_IMMUTABLE",
|
||||
.description_good = "Service cannot mark files immutable",
|
||||
.description_bad = "Service may mark files immutable",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1132,6 +1170,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_IPC_LOCK",
|
||||
.json_field = "CapabilityBoundingSet_CAP_IPC_LOCK",
|
||||
.description_good = "Service cannot lock memory into RAM",
|
||||
.description_bad = "Service may lock memory into RAM",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1142,6 +1181,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_CHROOT",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_CHROOT",
|
||||
.description_good = "Service cannot issue chroot()",
|
||||
.description_bad = "Service may issue chroot()",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1152,6 +1192,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_BLOCK_SUSPEND",
|
||||
.json_field = "CapabilityBoundingSet_CAP_BLOCK_SUSPEND",
|
||||
.description_good = "Service cannot establish wake locks",
|
||||
.description_bad = "Service may establish wake locks",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1162,6 +1203,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_WAKE_ALARM",
|
||||
.json_field = "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",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1172,6 +1214,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_LEASE",
|
||||
.json_field = "CapabilityBoundingSet_CAP_LEASE",
|
||||
.description_good = "Service cannot create file leases",
|
||||
.description_bad = "Service may create file leases",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1182,6 +1225,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_TTY_CONFIG",
|
||||
.description_good = "Service cannot issue vhangup()",
|
||||
.description_bad = "Service may issue vhangup()",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1192,6 +1236,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "CapabilityBoundingSet=~CAP_SYS_PACCT",
|
||||
.json_field = "CapabilityBoundingSet_CAP_SYS_PACCT",
|
||||
.description_good = "Service cannot use acct()",
|
||||
.description_bad = "Service may use acct()",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
|
||||
@ -1202,6 +1247,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "UMask=",
|
||||
.json_field = "UMask",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#UMask=",
|
||||
.weight = 100,
|
||||
.range = 10,
|
||||
@ -1209,6 +1255,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "KeyringMode=",
|
||||
.json_field = "KeyringMode",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#KeyringMode=",
|
||||
.description_good = "Service doesn't share key material with other services",
|
||||
.description_bad = "Service shares key material with other service",
|
||||
@ -1218,6 +1265,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProtectProc=",
|
||||
.json_field = "ProtectProc",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectProc=",
|
||||
.description_good = "Service has restricted access to process tree (/proc hidepid=)",
|
||||
.description_bad = "Service has full access to process tree (/proc hidepid=)",
|
||||
@ -1227,6 +1275,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "ProcSubset=",
|
||||
.json_field = "ProcSubset",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#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=)",
|
||||
@ -1236,6 +1285,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "NotifyAccess=",
|
||||
.json_field = "NotifyAccess",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NotifyAccess=",
|
||||
.description_good = "Service child processes cannot alter service state",
|
||||
.description_bad = "Service child processes may alter service state",
|
||||
@ -1245,6 +1295,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RemoveIPC=",
|
||||
.json_field = "RemoveIPC",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RemoveIPC=",
|
||||
.description_good = "Service user cannot leave SysV IPC objects around",
|
||||
.description_bad = "Service user may leave SysV IPC objects around",
|
||||
@ -1256,6 +1307,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "Delegate=",
|
||||
.json_field = "Delegate",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Delegate=",
|
||||
.description_good = "Service does not maintain its own delegated control group subtree",
|
||||
.description_bad = "Service maintains its own delegated control group subtree",
|
||||
@ -1267,6 +1319,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictRealtime=",
|
||||
.json_field = "RestrictRealtime",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictRealtime=",
|
||||
.description_good = "Service realtime scheduling access is restricted",
|
||||
.description_bad = "Service may acquire realtime scheduling",
|
||||
@ -1277,6 +1330,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictSUIDSGID=",
|
||||
.json_field = "RestrictSUIDSGID",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=",
|
||||
.description_good = "SUID/SGID file creation by service is restricted",
|
||||
.description_bad = "Service may create SUID/SGID files",
|
||||
@ -1287,6 +1341,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWUSER",
|
||||
.json_field = "RestrictNamespaces_CLONE_NEWUSER",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
.description_good = "Service cannot create user namespaces",
|
||||
.description_bad = "Service may create user namespaces",
|
||||
@ -1297,6 +1352,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWNS",
|
||||
.json_field = "RestrictNamespaces_CLONE_NEWNS",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
.description_good = "Service cannot create file system namespaces",
|
||||
.description_bad = "Service may create file system namespaces",
|
||||
@ -1307,6 +1363,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWIPC",
|
||||
.json_field = "RestrictNamespaces_CLONE_NEWIPC",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
.description_good = "Service cannot create IPC namespaces",
|
||||
.description_bad = "Service may create IPC namespaces",
|
||||
@ -1317,6 +1374,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWPID",
|
||||
.json_field = "RestrictNamespaces_CLONE_NEWPID",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
.description_good = "Service cannot create process namespaces",
|
||||
.description_bad = "Service may create process namespaces",
|
||||
@ -1327,6 +1385,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWCGROUP",
|
||||
.json_field = "RestrictNamespaces_CLONE_NEWCGROUP",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
.description_good = "Service cannot create cgroup namespaces",
|
||||
.description_bad = "Service may create cgroup namespaces",
|
||||
@ -1337,6 +1396,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWNET",
|
||||
.json_field = "RestrictNamespaces_CLONE_NEWNET",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
.description_good = "Service cannot create network namespaces",
|
||||
.description_bad = "Service may create network namespaces",
|
||||
@ -1347,6 +1407,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictNamespaces=~CLONE_NEWUTS",
|
||||
.json_field = "RestrictNamespaces_CLONE_NEWUTS",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
|
||||
.description_good = "Service cannot create hostname namespaces",
|
||||
.description_bad = "Service may create hostname namespaces",
|
||||
@ -1357,6 +1418,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictAddressFamilies=~AF_(INET|INET6)",
|
||||
.json_field = "RestrictAddressFamilies_AF_INET_INET6",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
|
||||
.description_good = "Service cannot allocate Internet sockets",
|
||||
.description_bad = "Service may allocate Internet sockets",
|
||||
@ -1367,6 +1429,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictAddressFamilies=~AF_UNIX",
|
||||
.json_field = "RestrictAddressFamilies_AF_UNIX",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
|
||||
.description_good = "Service cannot allocate local sockets",
|
||||
.description_bad = "Service may allocate local sockets",
|
||||
@ -1377,6 +1440,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictAddressFamilies=~AF_NETLINK",
|
||||
.json_field = "RestrictAddressFamilies_AF_NETLINK",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
|
||||
.description_good = "Service cannot allocate netlink sockets",
|
||||
.description_bad = "Service may allocate netlink sockets",
|
||||
@ -1387,6 +1451,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictAddressFamilies=~AF_PACKET",
|
||||
.json_field = "RestrictAddressFamilies_AF_PACKET",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
|
||||
.description_good = "Service cannot allocate packet sockets",
|
||||
.description_bad = "Service may allocate packet sockets",
|
||||
@ -1397,6 +1462,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "RestrictAddressFamilies=~…",
|
||||
.json_field = "RestrictAddressFamilies_OTHER",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
|
||||
.description_good = "Service cannot allocate exotic sockets",
|
||||
.description_bad = "Service may allocate exotic sockets",
|
||||
@ -1407,6 +1473,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallArchitectures=",
|
||||
.json_field = "SystemCallArchitectures",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallArchitectures=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1415,6 +1482,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
#if HAVE_SECCOMP
|
||||
{
|
||||
.id = "SystemCallFilter=~@swap",
|
||||
.json_field = "SystemCallFilter_swap",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1423,6 +1491,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@obsolete",
|
||||
.json_field = "SystemCallFilter_obsolete",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 250,
|
||||
.range = 10,
|
||||
@ -1431,6 +1500,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@clock",
|
||||
.json_field = "SystemCallFilter_clock",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1439,6 +1509,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@cpu-emulation",
|
||||
.json_field = "SystemCallFilter_cpu_emulation",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 250,
|
||||
.range = 10,
|
||||
@ -1447,6 +1518,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@debug",
|
||||
.json_field = "SystemCallFilter_debug",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1455,6 +1527,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@mount",
|
||||
.json_field = "SystemCallFilter_mount",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1463,6 +1536,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@module",
|
||||
.json_field = "SystemCallFilter_module",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1471,6 +1545,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@raw-io",
|
||||
.json_field = "SystemCallFilter_raw_io",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1479,6 +1554,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@reboot",
|
||||
.json_field = "SystemCallFilter_reboot",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1487,6 +1563,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@privileged",
|
||||
.json_field = "SystemCallFilter_privileged",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 700,
|
||||
.range = 10,
|
||||
@ -1495,6 +1572,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "SystemCallFilter=~@resources",
|
||||
.json_field = "SystemCallFilter_resources",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
|
||||
.weight = 700,
|
||||
.range = 10,
|
||||
@ -1504,6 +1582,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
#endif
|
||||
{
|
||||
.id = "IPAddressDeny=",
|
||||
.json_field = "IPAddressDeny",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#IPAddressDeny=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1511,6 +1590,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "DeviceAllow=",
|
||||
.json_field = "DeviceAllow",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DeviceAllow=",
|
||||
.weight = 1000,
|
||||
.range = 10,
|
||||
@ -1518,6 +1598,7 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
{
|
||||
.id = "AmbientCapabilities=",
|
||||
.json_field = "AmbientCapabilities",
|
||||
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#AmbientCapabilities=",
|
||||
.description_good = "Service process does not receive ambient capabilities",
|
||||
.description_bad = "Service process receives ambient capabilities",
|
||||
@ -1527,7 +1608,109 @@ static const struct security_assessor security_assessor_table[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static int assess(const SecurityInfo *info, Table *overview_table, AnalyzeSecurityFlags flags, unsigned threshold) {
|
||||
static JsonVariant* security_assessor_find_in_policy(const struct security_assessor *a, JsonVariant *policy, const char *name) {
|
||||
JsonVariant *item;
|
||||
assert(a);
|
||||
|
||||
if (!policy)
|
||||
return NULL;
|
||||
if (!json_variant_is_object(policy)) {
|
||||
log_debug("Specificied policy is not a JSON object, ignoring.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
item = json_variant_by_key(policy, a->json_field);
|
||||
if (!item)
|
||||
return NULL;
|
||||
if (!json_variant_is_object(item)) {
|
||||
log_debug("Item for '%s' in policy JSON object is not an object, ignoring.", a->id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return name ? json_variant_by_key(item, name) : item;
|
||||
}
|
||||
|
||||
static uint64_t access_weight(const struct security_assessor *a, JsonVariant *policy) {
|
||||
JsonVariant *val;
|
||||
|
||||
assert(a);
|
||||
|
||||
val = security_assessor_find_in_policy(a, policy, "weight");
|
||||
if (val) {
|
||||
if (json_variant_is_unsigned(val))
|
||||
return json_variant_unsigned(val);
|
||||
log_debug("JSON field 'weight' of policy for %s is not an unsigned integer, ignoring.", a->id);
|
||||
}
|
||||
|
||||
return a->weight;
|
||||
}
|
||||
|
||||
static uint64_t access_range(const struct security_assessor *a, JsonVariant *policy) {
|
||||
JsonVariant *val;
|
||||
|
||||
assert(a);
|
||||
|
||||
val = security_assessor_find_in_policy(a, policy, "range");
|
||||
if (val) {
|
||||
if (json_variant_is_unsigned(val))
|
||||
return json_variant_unsigned(val);
|
||||
log_debug("JSON field 'range' of policy for %s is not an unsigned integer, ignoring.", a->id);
|
||||
}
|
||||
|
||||
return a->range;
|
||||
}
|
||||
|
||||
static const char *access_description_na(const struct security_assessor *a, JsonVariant *policy) {
|
||||
JsonVariant *val;
|
||||
|
||||
assert(a);
|
||||
|
||||
val = security_assessor_find_in_policy(a, policy, "description_na");
|
||||
if (val) {
|
||||
if (json_variant_is_string(val))
|
||||
return json_variant_string(val);
|
||||
log_debug("JSON field 'description_na' of policy for %s is not a string, ignoring.", a->id);
|
||||
}
|
||||
|
||||
return a->description_na;
|
||||
}
|
||||
|
||||
static const char *access_description_good(const struct security_assessor *a, JsonVariant *policy) {
|
||||
JsonVariant *val;
|
||||
|
||||
assert(a);
|
||||
|
||||
val = security_assessor_find_in_policy(a, policy, "description_good");
|
||||
if (val) {
|
||||
if (json_variant_is_string(val))
|
||||
return json_variant_string(val);
|
||||
log_debug("JSON field 'description_good' of policy for %s is not a string, ignoring.", a->id);
|
||||
}
|
||||
|
||||
return a->description_good;
|
||||
}
|
||||
|
||||
static const char *access_description_bad(const struct security_assessor *a, JsonVariant *policy) {
|
||||
JsonVariant *val;
|
||||
|
||||
assert(a);
|
||||
|
||||
val = security_assessor_find_in_policy(a, policy, "description_bad");
|
||||
if (val) {
|
||||
if (json_variant_is_string(val))
|
||||
return json_variant_string(val);
|
||||
log_debug("JSON field 'description_bad' of policy for %s is not a string, ignoring.", a->id);
|
||||
}
|
||||
|
||||
return a->description_bad;
|
||||
}
|
||||
|
||||
static int assess(const SecurityInfo *info,
|
||||
Table *overview_table,
|
||||
AnalyzeSecurityFlags flags,
|
||||
unsigned threshold,
|
||||
JsonVariant *policy) {
|
||||
|
||||
static const struct {
|
||||
uint64_t exposure;
|
||||
const char *name;
|
||||
@ -1565,6 +1748,8 @@ static int assess(const SecurityInfo *info, Table *overview_table, AnalyzeSecuri
|
||||
_cleanup_free_ char *d = NULL;
|
||||
uint64_t badness;
|
||||
void *data;
|
||||
uint64_t weight = access_weight(a, policy);
|
||||
uint64_t range = access_range(a, policy);
|
||||
|
||||
data = (uint8_t *) info + a->offset;
|
||||
|
||||
@ -1579,29 +1764,30 @@ static int assess(const SecurityInfo *info, Table *overview_table, AnalyzeSecuri
|
||||
return r;
|
||||
}
|
||||
|
||||
assert(a->range > 0);
|
||||
assert(range > 0);
|
||||
|
||||
if (badness != UINT64_MAX) {
|
||||
assert(badness <= a->range);
|
||||
assert(badness <= range);
|
||||
|
||||
badness_sum += DIV_ROUND_UP(badness * a->weight, a->range);
|
||||
weight_sum += a->weight;
|
||||
badness_sum += DIV_ROUND_UP(badness * weight, range);
|
||||
weight_sum += weight;
|
||||
}
|
||||
|
||||
if (details_table) {
|
||||
const char *checkmark, *description, *color = NULL;
|
||||
const char *id = a->id;
|
||||
|
||||
if (badness == UINT64_MAX) {
|
||||
checkmark = " ";
|
||||
description = a->description_na;
|
||||
description = access_description_na(a, policy);
|
||||
color = NULL;
|
||||
} else if (badness == a->range) {
|
||||
checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK);
|
||||
description = a->description_bad;
|
||||
description = access_description_bad(a, policy);
|
||||
color = ansi_highlight_red();
|
||||
} else if (badness == 0) {
|
||||
checkmark = special_glyph(SPECIAL_GLYPH_CHECK_MARK);
|
||||
description = a->description_good;
|
||||
description = access_description_good(a, policy);
|
||||
color = ansi_highlight_green();
|
||||
} else {
|
||||
checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK);
|
||||
@ -1612,17 +1798,20 @@ static int assess(const SecurityInfo *info, Table *overview_table, AnalyzeSecuri
|
||||
if (d)
|
||||
description = d;
|
||||
|
||||
if (json_variant_by_key(policy, a->json_field) != NULL)
|
||||
id = a->json_field;
|
||||
|
||||
r = table_add_many(details_table,
|
||||
TABLE_STRING, checkmark,
|
||||
TABLE_SET_MINIMUM_WIDTH, 1,
|
||||
TABLE_SET_MAXIMUM_WIDTH, 1,
|
||||
TABLE_SET_ELLIPSIZE_PERCENT, 0,
|
||||
TABLE_SET_COLOR, color,
|
||||
TABLE_STRING, a->id, TABLE_SET_URL, a->url,
|
||||
TABLE_STRING, id, TABLE_SET_URL, a->url,
|
||||
TABLE_STRING, description,
|
||||
TABLE_UINT64, a->weight, TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_UINT64, weight, TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_UINT64, badness, TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_UINT64, a->range, TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_UINT64, range, TABLE_SET_ALIGN_PERCENT, 100,
|
||||
TABLE_EMPTY, TABLE_SET_ALIGN_PERCENT, 100);
|
||||
if (r < 0)
|
||||
return table_log_add_error(r);
|
||||
@ -2192,8 +2381,12 @@ static int acquire_security_info(sd_bus *bus, const char *name, SecurityInfo *in
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int analyze_security_one(sd_bus *bus, const char *name, Table *overview_table,
|
||||
AnalyzeSecurityFlags flags, unsigned threshold) {
|
||||
static int analyze_security_one(sd_bus *bus,
|
||||
const char *name,
|
||||
Table *overview_table,
|
||||
AnalyzeSecurityFlags flags,
|
||||
unsigned threshold,
|
||||
JsonVariant *policy) {
|
||||
|
||||
_cleanup_(security_info_freep) SecurityInfo *info = security_info_new();
|
||||
if (!info)
|
||||
@ -2210,7 +2403,7 @@ static int analyze_security_one(sd_bus *bus, const char *name, Table *overview_t
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = assess(info, overview_table, flags, threshold);
|
||||
r = assess(info, overview_table, flags, threshold, policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2396,7 +2589,7 @@ static int get_security_info(Unit *u, ExecContext *c, CGroupContext *g, Security
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int offline_security_check(Unit *u, unsigned threshold) {
|
||||
static int offline_security_check(Unit *u, unsigned threshold, JsonVariant *policy) {
|
||||
_cleanup_(table_unrefp) Table *overview_table = NULL;
|
||||
AnalyzeSecurityFlags flags = 0;
|
||||
_cleanup_(security_info_freep) SecurityInfo *info = NULL;
|
||||
@ -2411,10 +2604,17 @@ static int offline_security_check(Unit *u, unsigned threshold) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return assess(info, overview_table, flags, threshold);
|
||||
return assess(info, overview_table, flags, threshold, policy);
|
||||
}
|
||||
|
||||
static int offline_security_checks(char **filenames, UnitFileScope scope, bool check_man, bool run_generators, unsigned threshold, const char *root) {
|
||||
static int offline_security_checks(char **filenames,
|
||||
JsonVariant *policy,
|
||||
UnitFileScope scope,
|
||||
bool check_man,
|
||||
bool run_generators,
|
||||
unsigned threshold,
|
||||
const char *root) {
|
||||
|
||||
const ManagerTestRunFlags flags =
|
||||
MANAGER_TEST_RUN_MINIMAL |
|
||||
MANAGER_TEST_RUN_ENV_GENERATORS |
|
||||
@ -2473,7 +2673,7 @@ static int offline_security_checks(char **filenames, UnitFileScope scope, bool c
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
k = offline_security_check(units[i], threshold);
|
||||
k = offline_security_check(units[i], threshold, policy);
|
||||
if (k < 0 && r == 0)
|
||||
r = k;
|
||||
}
|
||||
@ -2481,8 +2681,16 @@ static int offline_security_checks(char **filenames, UnitFileScope scope, bool c
|
||||
return r;
|
||||
}
|
||||
|
||||
int analyze_security(sd_bus *bus, char **units, UnitFileScope scope, bool check_man, bool run_generators,
|
||||
bool offline, unsigned threshold, const char *root, AnalyzeSecurityFlags flags) {
|
||||
int analyze_security(sd_bus *bus,
|
||||
char **units,
|
||||
JsonVariant *policy,
|
||||
UnitFileScope scope,
|
||||
bool check_man,
|
||||
bool run_generators,
|
||||
bool offline,
|
||||
unsigned threshold,
|
||||
const char *root,
|
||||
AnalyzeSecurityFlags flags) {
|
||||
|
||||
_cleanup_(table_unrefp) Table *overview_table = NULL;
|
||||
int ret = 0, r;
|
||||
@ -2490,7 +2698,7 @@ int analyze_security(sd_bus *bus, char **units, UnitFileScope scope, bool check_
|
||||
assert(bus);
|
||||
|
||||
if (offline)
|
||||
return offline_security_checks(units, scope, check_man, run_generators, threshold, root);
|
||||
return offline_security_checks(units, policy, scope, check_man, run_generators, threshold, root);
|
||||
|
||||
if (strv_length(units) != 1) {
|
||||
overview_table = table_new("unit", "exposure", "predicate", "happy");
|
||||
@ -2550,7 +2758,7 @@ int analyze_security(sd_bus *bus, char **units, UnitFileScope scope, bool check_
|
||||
flags |= ANALYZE_SECURITY_SHORT|ANALYZE_SECURITY_ONLY_LOADED|ANALYZE_SECURITY_ONLY_LONG_RUNNING;
|
||||
|
||||
STRV_FOREACH(i, list) {
|
||||
r = analyze_security_one(bus, *i, overview_table, flags, threshold);
|
||||
r = analyze_security_one(bus, *i, overview_table, flags, threshold, policy);
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
}
|
||||
@ -2585,7 +2793,7 @@ int analyze_security(sd_bus *bus, char **units, UnitFileScope scope, bool check_
|
||||
} else
|
||||
name = mangled;
|
||||
|
||||
r = analyze_security_one(bus, name, overview_table, flags, threshold);
|
||||
r = analyze_security_one(bus, name, overview_table, flags, threshold, policy);
|
||||
if (r < 0 && ret >= 0)
|
||||
ret = r;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "json.h"
|
||||
#include "unit-file.h"
|
||||
|
||||
typedef enum AnalyzeSecurityFlags {
|
||||
@ -13,5 +14,13 @@ typedef enum AnalyzeSecurityFlags {
|
||||
ANALYZE_SECURITY_ONLY_LONG_RUNNING = 1 << 2,
|
||||
} AnalyzeSecurityFlags;
|
||||
|
||||
int analyze_security(sd_bus *bus, char **units, UnitFileScope scope, bool check_man, bool run_generators,
|
||||
bool offline, unsigned threshold, const char *root, AnalyzeSecurityFlags flags);
|
||||
int analyze_security(sd_bus *bus,
|
||||
char **units,
|
||||
JsonVariant *policy,
|
||||
UnitFileScope scope,
|
||||
bool check_man,
|
||||
bool run_generators,
|
||||
bool offline,
|
||||
unsigned threshold,
|
||||
const char *root,
|
||||
AnalyzeSecurityFlags flags);
|
||||
|
@ -91,6 +91,7 @@ static bool arg_man = true;
|
||||
static bool arg_generators = false;
|
||||
static char *arg_root = NULL;
|
||||
static char *arg_image = NULL;
|
||||
static char *arg_security_policy = NULL;
|
||||
static bool arg_offline = false;
|
||||
static unsigned arg_threshold = 100;
|
||||
static unsigned arg_iterations = 1;
|
||||
@ -100,6 +101,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_dot_from_patterns, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_dot_to_patterns, strv_freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_root, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_image, freep);
|
||||
STATIC_DESTRUCTOR_REGISTER(arg_security_policy, freep);
|
||||
|
||||
typedef struct BootTimes {
|
||||
usec_t firmware_time;
|
||||
@ -2154,7 +2156,9 @@ static int do_verify(int argc, char *argv[], void *userdata) {
|
||||
|
||||
static int do_security(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
|
||||
_cleanup_(json_variant_unrefp) JsonVariant *policy = NULL;
|
||||
int r;
|
||||
unsigned line, column;
|
||||
|
||||
r = acquire_bus(&bus, NULL);
|
||||
if (r < 0)
|
||||
@ -2162,7 +2166,35 @@ static int do_security(int argc, char *argv[], void *userdata) {
|
||||
|
||||
(void) pager_open(arg_pager_flags);
|
||||
|
||||
return analyze_security(bus, strv_skip(argv, 1), arg_scope, arg_man, arg_generators, arg_offline, arg_threshold, arg_root, 0);
|
||||
if (arg_security_policy) {
|
||||
r = json_parse_file(/*f=*/ NULL, arg_security_policy, /*flags=*/ 0, &policy, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse '%s' at %u:%u: %m", arg_security_policy, line, column);
|
||||
} else {
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
_cleanup_free_ char *pp = NULL;
|
||||
|
||||
r = search_and_fopen_nulstr("systemd-analyze-security.policy", "re", /*root=*/ NULL, CONF_PATHS_NULSTR("systemd"), &f, &pp);
|
||||
if (r < 0 && r != -ENOENT)
|
||||
return r;
|
||||
|
||||
if (f != NULL) {
|
||||
r = json_parse_file(f, pp, /*flags=*/ 0, &policy, &line, &column);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "[%s:%u:%u] Failed to parse JSON policy: %m", pp, line, column);
|
||||
}
|
||||
}
|
||||
|
||||
return analyze_security(bus,
|
||||
strv_skip(argv, 1),
|
||||
policy,
|
||||
arg_scope,
|
||||
arg_man,
|
||||
arg_generators,
|
||||
arg_offline,
|
||||
arg_threshold,
|
||||
arg_root,
|
||||
/*flags=*/ 0);
|
||||
}
|
||||
|
||||
static int help(int argc, char *argv[], void *userdata) {
|
||||
@ -2214,6 +2246,8 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
" --threshold=N Exit with a non-zero status when overall\n"
|
||||
" exposure level is over threshold value\n"
|
||||
" --version Show package version\n"
|
||||
" --security-policy=PATH Use custom JSON security policy instead\n"
|
||||
" of built-in one\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --system Operate on system systemd instance\n"
|
||||
" --user Operate on user systemd instance\n"
|
||||
@ -2266,6 +2300,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_RECURSIVE_ERRORS,
|
||||
ARG_OFFLINE,
|
||||
ARG_THRESHOLD,
|
||||
ARG_SECURITY_POLICY,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -2278,6 +2313,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "recursive-errors", required_argument, NULL, ARG_RECURSIVE_ERRORS },
|
||||
{ "offline", required_argument, NULL, ARG_OFFLINE },
|
||||
{ "threshold", required_argument, NULL, ARG_THRESHOLD },
|
||||
{ "security-policy", required_argument, NULL, ARG_SECURITY_POLICY },
|
||||
{ "system", no_argument, NULL, ARG_SYSTEM },
|
||||
{ "user", no_argument, NULL, ARG_USER },
|
||||
{ "global", no_argument, NULL, ARG_GLOBAL },
|
||||
@ -2409,6 +2445,12 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
break;
|
||||
|
||||
case ARG_SECURITY_POLICY:
|
||||
r = parse_path_argument(optarg, /* suppress_root= */ false, &arg_security_policy);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_ITERATIONS:
|
||||
r = safe_atou(optarg, &arg_iterations);
|
||||
if (r < 0)
|
||||
@ -2447,6 +2489,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --user is not supported for cat-config right now.");
|
||||
|
||||
if (arg_security_policy && !streq_ptr(argv[optind], "security"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Option --security-policy= is only supported for security.");
|
||||
|
||||
if ((arg_root || arg_image) && (!STRPTR_IN_SET(argv[optind], "cat-config", "verify")) &&
|
||||
(!(streq_ptr(argv[optind], "security") && arg_offline)))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
|
1
test/TEST-63-ANALYZE/Makefile
Symbolic link
1
test/TEST-63-ANALYZE/Makefile
Symbolic link
@ -0,0 +1 @@
|
||||
../TEST-01-BASIC/Makefile
|
9
test/TEST-63-ANALYZE/test.sh
Executable file
9
test/TEST-63-ANALYZE/test.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
TEST_DESCRIPTION="test analyze"
|
||||
|
||||
# shellcheck source=test/test-functions
|
||||
. "${TEST_BASE_DIR:?}/test-functions"
|
||||
|
||||
do_test "$@"
|
574
test/units/testsuite-63.sh
Executable file
574
test/units/testsuite-63.sh
Executable file
@ -0,0 +1,574 @@
|
||||
#!/usr/bin/env bash
|
||||
# shellcheck disable=SC2016
|
||||
set -eux
|
||||
|
||||
systemd-analyze log-level debug
|
||||
|
||||
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
|
||||
# Non-zero exit status since all associated dependencies are recusrively loaded when the unit file is loaded
|
||||
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
|
||||
EOF
|
||||
|
||||
|
||||
# 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
|
||||
|
||||
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
|
||||
{"User_Or_DynamicUser":
|
||||
{"description_bad": "Service runs as root user",
|
||||
"weight": 2000,
|
||||
"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
|
||||
},
|
||||
"RootDirectory_Or_RootImage":
|
||||
{"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
|
||||
},
|
||||
"RestrictNamespaces_CLONE_NEWUSER":
|
||||
{"description_good": "Servicecannotcreateusernamespaces",
|
||||
"description_bad": "Servicemaycreateusernamespaces",
|
||||
"weight": 1500,
|
||||
"range": 1
|
||||
},
|
||||
"RestrictNamespaces_CLONE_NEWNS":
|
||||
{"description_good": "Service cannot create file system namespaces",
|
||||
"description_bad": "Service may create file system namespaces",
|
||||
"weight": 500,
|
||||
"range": 1
|
||||
},
|
||||
"RestrictNamespaces_CLONE_NEWIPC":
|
||||
{"description_good": "Service cannot create IPC namespaces",
|
||||
"description_bad": "Service may create IPC namespaces",
|
||||
"weight": 500,
|
||||
"range": 1
|
||||
},
|
||||
"RestrictNamespaces_CLONE_NEWPID":
|
||||
{"description_good": "Service cannot create process namespaces",
|
||||
"description_bad": "Service may create process namespaces",
|
||||
"weight": 500,
|
||||
"range": 1
|
||||
},
|
||||
"RestrictNamespaces_CLONE_NEWCGROUP":
|
||||
{"description_good": "Service cannot create cgroup namespaces",
|
||||
"description_bad": "Service may create cgroup namespaces",
|
||||
"weight": 500,
|
||||
"range": 1
|
||||
},
|
||||
"RestrictNamespaces_CLONE_NEWNET":
|
||||
{"description_good": "Service cannot create network namespaces",
|
||||
"description_bad": "Service may create network namespaces",
|
||||
"weight": 500,
|
||||
"range": 1
|
||||
},
|
||||
"RestrictNamespaces_CLONE_NEWUTS":
|
||||
{"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
|
||||
|
||||
set +e
|
||||
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
|
||||
|
||||
systemd-analyze log-level info
|
||||
|
||||
echo OK >/testok
|
||||
|
||||
exit 0
|
Loading…
x
Reference in New Issue
Block a user