struct security_assessor {
const char *id;
+ const char *json_field;
const char *description_good;
const char *description_bad;
const char *description_na;
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,
},
{
.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",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.id = "ProtectHome=",
+ .json_field = "ProtectHome",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=",
.weight = 1000,
.range = 10,
},
{
.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=",
},
{
.id = "ProtectSystem=",
+ .json_field = "ProtectSystem",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=",
.weight = 1000,
.range = 10,
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.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=",
},
{
.id = "UMask=",
+ .json_field = "UMask",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#UMask=",
.weight = 100,
.range = 10,
},
{
.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",
},
{
.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=)",
},
{
.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=)",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.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",
},
{
.id = "SystemCallArchitectures=",
+ .json_field = "SystemCallArchitectures",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallArchitectures=",
.weight = 1000,
.range = 10,
#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,
},
{
.id = "SystemCallFilter=~@obsolete",
+ .json_field = "SystemCallFilter_obsolete",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 250,
.range = 10,
},
{
.id = "SystemCallFilter=~@clock",
+ .json_field = "SystemCallFilter_clock",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 1000,
.range = 10,
},
{
.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,
},
{
.id = "SystemCallFilter=~@debug",
+ .json_field = "SystemCallFilter_debug",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 1000,
.range = 10,
},
{
.id = "SystemCallFilter=~@mount",
+ .json_field = "SystemCallFilter_mount",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 1000,
.range = 10,
},
{
.id = "SystemCallFilter=~@module",
+ .json_field = "SystemCallFilter_module",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 1000,
.range = 10,
},
{
.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,
},
{
.id = "SystemCallFilter=~@reboot",
+ .json_field = "SystemCallFilter_reboot",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 1000,
.range = 10,
},
{
.id = "SystemCallFilter=~@privileged",
+ .json_field = "SystemCallFilter_privileged",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 700,
.range = 10,
},
{
.id = "SystemCallFilter=~@resources",
+ .json_field = "SystemCallFilter_resources",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
.weight = 700,
.range = 10,
#endif
{
.id = "IPAddressDeny=",
+ .json_field = "IPAddressDeny",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#IPAddressDeny=",
.weight = 1000,
.range = 10,
},
{
.id = "DeviceAllow=",
+ .json_field = "DeviceAllow",
.url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DeviceAllow=",
.weight = 1000,
.range = 10,
},
{
.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",
},
};
-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;
_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;
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);
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);
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)
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;
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;
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 |
}
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;
}
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");
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;
}
} 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;
}