LCOV - code coverage report
Current view: top level - analyze - analyze-security.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 0 653 0.0 %
Date: 2019-08-23 13:36:53 Functions: 0 29 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 592 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <sched.h>
       4                 :            : #include <sys/utsname.h>
       5                 :            : 
       6                 :            : #include "analyze-security.h"
       7                 :            : #include "bus-error.h"
       8                 :            : #include "bus-unit-util.h"
       9                 :            : #include "bus-util.h"
      10                 :            : #include "env-util.h"
      11                 :            : #include "format-table.h"
      12                 :            : #include "in-addr-util.h"
      13                 :            : #include "locale-util.h"
      14                 :            : #include "macro.h"
      15                 :            : #include "missing.h"
      16                 :            : #include "nulstr-util.h"
      17                 :            : #include "parse-util.h"
      18                 :            : #include "path-util.h"
      19                 :            : #include "pretty-print.h"
      20                 :            : #if HAVE_SECCOMP
      21                 :            : #  include "seccomp-util.h"
      22                 :            : #endif
      23                 :            : #include "set.h"
      24                 :            : #include "stdio-util.h"
      25                 :            : #include "strv.h"
      26                 :            : #include "terminal-util.h"
      27                 :            : #include "unit-def.h"
      28                 :            : #include "unit-name.h"
      29                 :            : 
      30                 :            : struct security_info {
      31                 :            :         char *id;
      32                 :            :         char *type;
      33                 :            :         char *load_state;
      34                 :            :         char *fragment_path;
      35                 :            :         bool default_dependencies;
      36                 :            : 
      37                 :            :         uint64_t ambient_capabilities;
      38                 :            :         uint64_t capability_bounding_set;
      39                 :            : 
      40                 :            :         char *user;
      41                 :            :         char **supplementary_groups;
      42                 :            :         bool dynamic_user;
      43                 :            : 
      44                 :            :         bool ip_address_deny_all;
      45                 :            :         bool ip_address_allow_localhost;
      46                 :            :         bool ip_address_allow_other;
      47                 :            : 
      48                 :            :         bool ip_filters_custom_ingress;
      49                 :            :         bool ip_filters_custom_egress;
      50                 :            : 
      51                 :            :         char *keyring_mode;
      52                 :            :         bool lock_personality;
      53                 :            :         bool memory_deny_write_execute;
      54                 :            :         bool no_new_privileges;
      55                 :            :         char *notify_access;
      56                 :            :         bool protect_hostname;
      57                 :            : 
      58                 :            :         bool private_devices;
      59                 :            :         bool private_mounts;
      60                 :            :         bool private_network;
      61                 :            :         bool private_tmp;
      62                 :            :         bool private_users;
      63                 :            : 
      64                 :            :         bool protect_control_groups;
      65                 :            :         bool protect_kernel_modules;
      66                 :            :         bool protect_kernel_tunables;
      67                 :            : 
      68                 :            :         char *protect_home;
      69                 :            :         char *protect_system;
      70                 :            : 
      71                 :            :         bool remove_ipc;
      72                 :            : 
      73                 :            :         bool restrict_address_family_inet;
      74                 :            :         bool restrict_address_family_unix;
      75                 :            :         bool restrict_address_family_netlink;
      76                 :            :         bool restrict_address_family_packet;
      77                 :            :         bool restrict_address_family_other;
      78                 :            : 
      79                 :            :         uint64_t restrict_namespaces;
      80                 :            :         bool restrict_realtime;
      81                 :            :         bool restrict_suid_sgid;
      82                 :            : 
      83                 :            :         char *root_directory;
      84                 :            :         char *root_image;
      85                 :            : 
      86                 :            :         bool delegate;
      87                 :            :         char *device_policy;
      88                 :            :         bool device_allow_non_empty;
      89                 :            : 
      90                 :            :         char **system_call_architectures;
      91                 :            : 
      92                 :            :         bool system_call_filter_whitelist;
      93                 :            :         Set *system_call_filter;
      94                 :            : 
      95                 :            :         uint32_t _umask;
      96                 :            : };
      97                 :            : 
      98                 :            : struct security_assessor {
      99                 :            :         const char *id;
     100                 :            :         const char *description_good;
     101                 :            :         const char *description_bad;
     102                 :            :         const char *description_na;
     103                 :            :         const char *url;
     104                 :            :         uint64_t weight;
     105                 :            :         uint64_t range;
     106                 :            :         int (*assess)(
     107                 :            :                 const struct security_assessor *a,
     108                 :            :                 const struct security_info *info,
     109                 :            :                 const void *data,
     110                 :            :                 uint64_t *ret_badness,
     111                 :            :                 char **ret_description);
     112                 :            :         size_t offset;
     113                 :            :         uint64_t parameter;
     114                 :            :         bool default_dependencies_only;
     115                 :            : };
     116                 :            : 
     117                 :          0 : static void security_info_free(struct security_info *i) {
     118         [ #  # ]:          0 :         if (!i)
     119                 :          0 :                 return;
     120                 :            : 
     121                 :          0 :         free(i->id);
     122                 :          0 :         free(i->type);
     123                 :          0 :         free(i->load_state);
     124                 :          0 :         free(i->fragment_path);
     125                 :            : 
     126                 :          0 :         free(i->user);
     127                 :            : 
     128                 :          0 :         free(i->protect_home);
     129                 :          0 :         free(i->protect_system);
     130                 :            : 
     131                 :          0 :         free(i->root_directory);
     132                 :          0 :         free(i->root_image);
     133                 :            : 
     134                 :          0 :         free(i->keyring_mode);
     135                 :          0 :         free(i->notify_access);
     136                 :            : 
     137                 :          0 :         free(i->device_policy);
     138                 :            : 
     139                 :          0 :         strv_free(i->supplementary_groups);
     140                 :          0 :         strv_free(i->system_call_architectures);
     141                 :            : 
     142                 :          0 :         set_free_free(i->system_call_filter);
     143                 :            : }
     144                 :            : 
     145                 :          0 : static bool security_info_runs_privileged(const struct security_info *i)  {
     146         [ #  # ]:          0 :         assert(i);
     147                 :            : 
     148   [ #  #  #  #  :          0 :         if (STRPTR_IN_SET(i->user, "0", "root"))
                   #  # ]
     149                 :          0 :                 return true;
     150                 :            : 
     151         [ #  # ]:          0 :         if (i->dynamic_user)
     152                 :          0 :                 return false;
     153                 :            : 
     154                 :          0 :         return isempty(i->user);
     155                 :            : }
     156                 :            : 
     157                 :          0 : static int assess_bool(
     158                 :            :                 const struct security_assessor *a,
     159                 :            :                 const struct security_info *info,
     160                 :            :                 const void *data,
     161                 :            :                 uint64_t *ret_badness,
     162                 :            :                 char **ret_description) {
     163                 :            : 
     164                 :          0 :         const bool *b = data;
     165                 :            : 
     166         [ #  # ]:          0 :         assert(b);
     167         [ #  # ]:          0 :         assert(ret_badness);
     168         [ #  # ]:          0 :         assert(ret_description);
     169                 :            : 
     170         [ #  # ]:          0 :         *ret_badness = a->parameter ? *b : !*b;
     171                 :          0 :         *ret_description = NULL;
     172                 :            : 
     173                 :          0 :         return 0;
     174                 :            : }
     175                 :            : 
     176                 :          0 : static int assess_user(
     177                 :            :                 const struct security_assessor *a,
     178                 :            :                 const struct security_info *info,
     179                 :            :                 const void *data,
     180                 :            :                 uint64_t *ret_badness,
     181                 :            :                 char **ret_description) {
     182                 :            : 
     183                 :          0 :         _cleanup_free_ char *d = NULL;
     184                 :            :         uint64_t b;
     185                 :            : 
     186         [ #  # ]:          0 :         assert(ret_badness);
     187         [ #  # ]:          0 :         assert(ret_description);
     188                 :            : 
     189         [ #  # ]:          0 :         if (streq_ptr(info->user, NOBODY_USER_NAME)) {
     190                 :          0 :                 d = strdup("Service runs under as '" NOBODY_USER_NAME "' user, which should not be used for services");
     191                 :          0 :                 b = 9;
     192   [ #  #  #  # ]:          0 :         } else if (info->dynamic_user && !STR_IN_SET(info->user, "0", "root")) {
     193                 :          0 :                 d = strdup("Service runs under a transient non-root user identity");
     194                 :          0 :                 b = 0;
     195   [ #  #  #  # ]:          0 :         } else if (info->user && !STR_IN_SET(info->user, "0", "root", "")) {
     196                 :          0 :                 d = strdup("Service runs under a static non-root user identity");
     197                 :          0 :                 b = 0;
     198                 :            :         } else {
     199                 :          0 :                 *ret_badness = 10;
     200                 :          0 :                 *ret_description = NULL;
     201                 :          0 :                 return 0;
     202                 :            :         }
     203                 :            : 
     204         [ #  # ]:          0 :         if (!d)
     205                 :          0 :                 return log_oom();
     206                 :            : 
     207                 :          0 :         *ret_badness = b;
     208                 :          0 :         *ret_description = TAKE_PTR(d);
     209                 :            : 
     210                 :          0 :         return 0;
     211                 :            : }
     212                 :            : 
     213                 :          0 : static int assess_protect_home(
     214                 :            :                 const struct security_assessor *a,
     215                 :            :                 const struct security_info *info,
     216                 :            :                 const void *data,
     217                 :            :                 uint64_t *ret_badness,
     218                 :            :                 char **ret_description) {
     219                 :            : 
     220                 :            :         const char *description;
     221                 :            :         uint64_t badness;
     222                 :            :         char *copy;
     223                 :            :         int r;
     224                 :            : 
     225         [ #  # ]:          0 :         assert(ret_badness);
     226         [ #  # ]:          0 :         assert(ret_description);
     227                 :            : 
     228                 :          0 :         badness = 10;
     229                 :          0 :         description = "Service has full access to home directories";
     230                 :            : 
     231                 :          0 :         r = parse_boolean(info->protect_home);
     232         [ #  # ]:          0 :         if (r < 0) {
     233         [ #  # ]:          0 :                 if (streq_ptr(info->protect_home, "read-only")) {
     234                 :          0 :                         badness = 5;
     235                 :          0 :                         description = "Service has read-only access to home directories";
     236         [ #  # ]:          0 :                 } else if (streq_ptr(info->protect_home, "tmpfs")) {
     237                 :          0 :                         badness = 1;
     238                 :          0 :                         description = "Service has access to fake empty home directories";
     239                 :            :                 }
     240         [ #  # ]:          0 :         } else if (r > 0) {
     241                 :          0 :                 badness = 0;
     242                 :          0 :                 description = "Service has no access to home directories";
     243                 :            :         }
     244                 :            : 
     245                 :          0 :         copy = strdup(description);
     246         [ #  # ]:          0 :         if (!copy)
     247                 :          0 :                 return log_oom();
     248                 :            : 
     249                 :          0 :         *ret_badness = badness;
     250                 :          0 :         *ret_description = copy;
     251                 :            : 
     252                 :          0 :         return 0;
     253                 :            : }
     254                 :            : 
     255                 :          0 : static int assess_protect_system(
     256                 :            :                 const struct security_assessor *a,
     257                 :            :                 const struct security_info *info,
     258                 :            :                 const void *data,
     259                 :            :                 uint64_t *ret_badness,
     260                 :            :                 char **ret_description) {
     261                 :            : 
     262                 :            :         const char *description;
     263                 :            :         uint64_t badness;
     264                 :            :         char *copy;
     265                 :            :         int r;
     266                 :            : 
     267         [ #  # ]:          0 :         assert(ret_badness);
     268         [ #  # ]:          0 :         assert(ret_description);
     269                 :            : 
     270                 :          0 :         badness = 10;
     271                 :          0 :         description = "Service has full access to the OS file hierarchy";
     272                 :            : 
     273                 :          0 :         r = parse_boolean(info->protect_system);
     274         [ #  # ]:          0 :         if (r < 0) {
     275         [ #  # ]:          0 :                 if (streq_ptr(info->protect_system, "full")) {
     276                 :          0 :                         badness = 3;
     277                 :          0 :                         description = "Service has very limited write access to the OS file hierarchy";
     278         [ #  # ]:          0 :                 } else if (streq_ptr(info->protect_system, "strict")) {
     279                 :          0 :                         badness = 0;
     280                 :          0 :                         description = "Service has strict read-only access to the OS file hierarchy";
     281                 :            :                 }
     282         [ #  # ]:          0 :         } else if (r > 0) {
     283                 :          0 :                 badness = 5;
     284                 :          0 :                 description = "Service has limited write access to the OS file hierarchy";
     285                 :            :         }
     286                 :            : 
     287                 :          0 :         copy = strdup(description);
     288         [ #  # ]:          0 :         if (!copy)
     289                 :          0 :                 return log_oom();
     290                 :            : 
     291                 :          0 :         *ret_badness = badness;
     292                 :          0 :         *ret_description = copy;
     293                 :            : 
     294                 :          0 :         return 0;
     295                 :            : }
     296                 :            : 
     297                 :          0 : static int assess_root_directory(
     298                 :            :                 const struct security_assessor *a,
     299                 :            :                 const struct security_info *info,
     300                 :            :                 const void *data,
     301                 :            :                 uint64_t *ret_badness,
     302                 :            :                 char **ret_description) {
     303                 :            : 
     304         [ #  # ]:          0 :         assert(ret_badness);
     305         [ #  # ]:          0 :         assert(ret_description);
     306                 :            : 
     307                 :          0 :         *ret_badness =
     308   [ #  #  #  # ]:          0 :                 empty_or_root(info->root_directory) ||
     309                 :          0 :                 empty_or_root(info->root_image);
     310                 :          0 :         *ret_description = NULL;
     311                 :            : 
     312                 :          0 :         return 0;
     313                 :            : }
     314                 :            : 
     315                 :          0 : static int assess_capability_bounding_set(
     316                 :            :                 const struct security_assessor *a,
     317                 :            :                 const struct security_info *info,
     318                 :            :                 const void *data,
     319                 :            :                 uint64_t *ret_badness,
     320                 :            :                 char **ret_description) {
     321                 :            : 
     322         [ #  # ]:          0 :         assert(ret_badness);
     323         [ #  # ]:          0 :         assert(ret_description);
     324                 :            : 
     325                 :          0 :         *ret_badness = !!(info->capability_bounding_set & a->parameter);
     326                 :          0 :         *ret_description = NULL;
     327                 :            : 
     328                 :          0 :         return 0;
     329                 :            : }
     330                 :            : 
     331                 :          0 : static int assess_umask(
     332                 :            :                 const struct security_assessor *a,
     333                 :            :                 const struct security_info *info,
     334                 :            :                 const void *data,
     335                 :            :                 uint64_t *ret_badness,
     336                 :            :                 char **ret_description) {
     337                 :            : 
     338                 :          0 :         char *copy = NULL;
     339                 :            :         const char *d;
     340                 :            :         uint64_t b;
     341                 :            : 
     342         [ #  # ]:          0 :         assert(ret_badness);
     343         [ #  # ]:          0 :         assert(ret_description);
     344                 :            : 
     345         [ #  # ]:          0 :         if (!FLAGS_SET(info->_umask, 0002)) {
     346                 :          0 :                 d = "Files created by service are world-writable by default";
     347                 :          0 :                 b = 10;
     348         [ #  # ]:          0 :         } else if (!FLAGS_SET(info->_umask, 0004)) {
     349                 :          0 :                 d = "Files created by service are world-readable by default";
     350                 :          0 :                 b = 5;
     351         [ #  # ]:          0 :         } else if (!FLAGS_SET(info->_umask, 0020)) {
     352                 :          0 :                 d = "Files created by service are group-writable by default";
     353                 :          0 :                 b = 2;
     354         [ #  # ]:          0 :         } else if (!FLAGS_SET(info->_umask, 0040)) {
     355                 :          0 :                 d = "Files created by service are group-readable by default";
     356                 :          0 :                 b = 1;
     357                 :            :         } else {
     358                 :          0 :                 d = "Files created by service are accessible only by service's own user by default";
     359                 :          0 :                 b = 0;
     360                 :            :         }
     361                 :            : 
     362                 :          0 :         copy = strdup(d);
     363         [ #  # ]:          0 :         if (!copy)
     364                 :          0 :                 return log_oom();
     365                 :            : 
     366                 :          0 :         *ret_badness = b;
     367                 :          0 :         *ret_description = copy;
     368                 :            : 
     369                 :          0 :         return 0;
     370                 :            : }
     371                 :            : 
     372                 :          0 : static int assess_keyring_mode(
     373                 :            :                 const struct security_assessor *a,
     374                 :            :                 const struct security_info *info,
     375                 :            :                 const void *data,
     376                 :            :                 uint64_t *ret_badness,
     377                 :            :                 char **ret_description) {
     378                 :            : 
     379         [ #  # ]:          0 :         assert(ret_badness);
     380         [ #  # ]:          0 :         assert(ret_description);
     381                 :            : 
     382                 :          0 :         *ret_badness = !streq_ptr(info->keyring_mode, "private");
     383                 :          0 :         *ret_description = NULL;
     384                 :            : 
     385                 :          0 :         return 0;
     386                 :            : }
     387                 :            : 
     388                 :          0 : static int assess_notify_access(
     389                 :            :                 const struct security_assessor *a,
     390                 :            :                 const struct security_info *info,
     391                 :            :                 const void *data,
     392                 :            :                 uint64_t *ret_badness,
     393                 :            :                 char **ret_description) {
     394                 :            : 
     395         [ #  # ]:          0 :         assert(ret_badness);
     396         [ #  # ]:          0 :         assert(ret_description);
     397                 :            : 
     398                 :          0 :         *ret_badness = streq_ptr(info->notify_access, "all");
     399                 :          0 :         *ret_description = NULL;
     400                 :            : 
     401                 :          0 :         return 0;
     402                 :            : }
     403                 :            : 
     404                 :          0 : static int assess_remove_ipc(
     405                 :            :                 const struct security_assessor *a,
     406                 :            :                 const struct security_info *info,
     407                 :            :                 const void *data,
     408                 :            :                 uint64_t *ret_badness,
     409                 :            :                 char **ret_description) {
     410                 :            : 
     411         [ #  # ]:          0 :         assert(ret_badness);
     412         [ #  # ]:          0 :         assert(ret_description);
     413                 :            : 
     414         [ #  # ]:          0 :         if (security_info_runs_privileged(info))
     415                 :          0 :                 *ret_badness = UINT64_MAX;
     416                 :            :         else
     417                 :          0 :                 *ret_badness = !info->remove_ipc;
     418                 :            : 
     419                 :          0 :         *ret_description = NULL;
     420                 :          0 :         return 0;
     421                 :            : }
     422                 :            : 
     423                 :          0 : static int assess_supplementary_groups(
     424                 :            :                 const struct security_assessor *a,
     425                 :            :                 const struct security_info *info,
     426                 :            :                 const void *data,
     427                 :            :                 uint64_t *ret_badness,
     428                 :            :                 char **ret_description) {
     429                 :            : 
     430         [ #  # ]:          0 :         assert(ret_badness);
     431         [ #  # ]:          0 :         assert(ret_description);
     432                 :            : 
     433         [ #  # ]:          0 :         if (security_info_runs_privileged(info))
     434                 :          0 :                 *ret_badness = UINT64_MAX;
     435                 :            :         else
     436                 :          0 :                 *ret_badness = !strv_isempty(info->supplementary_groups);
     437                 :            : 
     438                 :          0 :         *ret_description = NULL;
     439                 :          0 :         return 0;
     440                 :            : }
     441                 :            : 
     442                 :          0 : static int assess_restrict_namespaces(
     443                 :            :                 const struct security_assessor *a,
     444                 :            :                 const struct security_info *info,
     445                 :            :                 const void *data,
     446                 :            :                 uint64_t *ret_badness,
     447                 :            :                 char **ret_description) {
     448                 :            : 
     449         [ #  # ]:          0 :         assert(ret_badness);
     450         [ #  # ]:          0 :         assert(ret_description);
     451                 :            : 
     452                 :          0 :         *ret_badness = !!(info->restrict_namespaces & a->parameter);
     453                 :          0 :         *ret_description = NULL;
     454                 :            : 
     455                 :          0 :         return 0;
     456                 :            : }
     457                 :            : 
     458                 :          0 : static int assess_system_call_architectures(
     459                 :            :                 const struct security_assessor *a,
     460                 :            :                 const struct security_info *info,
     461                 :            :                 const void *data,
     462                 :            :                 uint64_t *ret_badness,
     463                 :            :                 char **ret_description) {
     464                 :            : 
     465                 :            :         char *d;
     466                 :            :         uint64_t b;
     467                 :            : 
     468         [ #  # ]:          0 :         assert(ret_badness);
     469         [ #  # ]:          0 :         assert(ret_description);
     470                 :            : 
     471         [ #  # ]:          0 :         if (strv_isempty(info->system_call_architectures)) {
     472                 :          0 :                 b = 10;
     473                 :          0 :                 d = strdup("Service may execute system calls with all ABIs");
     474         [ #  # ]:          0 :         } else if (strv_equal(info->system_call_architectures, STRV_MAKE("native"))) {
     475                 :          0 :                 b = 0;
     476                 :          0 :                 d = strdup("Service may execute system calls only with native ABI");
     477                 :            :         } else {
     478                 :          0 :                 b = 8;
     479                 :          0 :                 d = strdup("Service may execute system calls with multiple ABIs");
     480                 :            :         }
     481                 :            : 
     482         [ #  # ]:          0 :         if (!d)
     483                 :          0 :                 return log_oom();
     484                 :            : 
     485                 :          0 :         *ret_badness = b;
     486                 :          0 :         *ret_description = d;
     487                 :            : 
     488                 :          0 :         return 0;
     489                 :            : }
     490                 :            : 
     491                 :            : #if HAVE_SECCOMP
     492                 :            : 
     493                 :          0 : static bool syscall_names_in_filter(Set *s, bool whitelist, const SyscallFilterSet *f) {
     494                 :            :         const char *syscall;
     495                 :            : 
     496   [ #  #  #  # ]:          0 :         NULSTR_FOREACH(syscall, f->value) {
     497                 :            :                 int id;
     498                 :            : 
     499         [ #  # ]:          0 :                 if (syscall[0] == '@') {
     500                 :            :                         const SyscallFilterSet *g;
     501                 :            : 
     502         [ #  # ]:          0 :                         assert_se(g = syscall_filter_set_find(syscall));
     503         [ #  # ]:          0 :                         if (syscall_names_in_filter(s, whitelist, g))
     504                 :          0 :                                 return true; /* bad! */
     505                 :            : 
     506                 :          0 :                         continue;
     507                 :            :                 }
     508                 :            : 
     509                 :            :                 /* Let's see if the system call actually exists on this platform, before complaining */
     510                 :          0 :                 id = seccomp_syscall_resolve_name(syscall);
     511         [ #  # ]:          0 :                 if (id < 0)
     512                 :          0 :                         continue;
     513                 :            : 
     514         [ #  # ]:          0 :                 if (set_contains(s, syscall) == whitelist) {
     515         [ #  # ]:          0 :                         log_debug("Offending syscall filter item: %s", syscall);
     516                 :          0 :                         return true; /* bad! */
     517                 :            :                 }
     518                 :            :         }
     519                 :            : 
     520                 :          0 :         return false;
     521                 :            : }
     522                 :            : 
     523                 :          0 : static int assess_system_call_filter(
     524                 :            :                 const struct security_assessor *a,
     525                 :            :                 const struct security_info *info,
     526                 :            :                 const void *data,
     527                 :            :                 uint64_t *ret_badness,
     528                 :            :                 char **ret_description) {
     529                 :            : 
     530                 :            :         const SyscallFilterSet *f;
     531                 :          0 :         char *d = NULL;
     532                 :            :         uint64_t b;
     533                 :            : 
     534         [ #  # ]:          0 :         assert(a);
     535         [ #  # ]:          0 :         assert(info);
     536         [ #  # ]:          0 :         assert(ret_badness);
     537         [ #  # ]:          0 :         assert(ret_description);
     538                 :            : 
     539         [ #  # ]:          0 :         assert(a->parameter < _SYSCALL_FILTER_SET_MAX);
     540                 :          0 :         f = syscall_filter_sets + a->parameter;
     541                 :            : 
     542   [ #  #  #  # ]:          0 :         if (!info->system_call_filter_whitelist && set_isempty(info->system_call_filter)) {
     543                 :          0 :                 d = strdup("Service does not filter system calls");
     544                 :          0 :                 b = 10;
     545                 :            :         } else {
     546                 :            :                 bool bad;
     547                 :            : 
     548         [ #  # ]:          0 :                 log_debug("Analyzing system call filter, checking against: %s", f->name);
     549                 :          0 :                 bad = syscall_names_in_filter(info->system_call_filter, info->system_call_filter_whitelist, f);
     550   [ #  #  #  # ]:          0 :                 log_debug("Result: %s", bad ? "bad" : "good");
     551                 :            : 
     552         [ #  # ]:          0 :                 if (info->system_call_filter_whitelist) {
     553         [ #  # ]:          0 :                         if (bad) {
     554                 :          0 :                                 (void) asprintf(&d, "System call whitelist defined for service, and %s is included", f->name);
     555                 :          0 :                                 b = 9;
     556                 :            :                         } else {
     557                 :          0 :                                 (void) asprintf(&d, "System call whitelist defined for service, and %s is not included", f->name);
     558                 :          0 :                                 b = 0;
     559                 :            :                         }
     560                 :            :                 } else {
     561         [ #  # ]:          0 :                         if (bad) {
     562                 :          0 :                                 (void) asprintf(&d, "System call blacklist defined for service, and %s is not included", f->name);
     563                 :          0 :                                 b = 10;
     564                 :            :                         } else {
     565                 :          0 :                                 (void) asprintf(&d, "System call blacklist defined for service, and %s is included", f->name);
     566                 :          0 :                                 b = 5;
     567                 :            :                         }
     568                 :            :                 }
     569                 :            :         }
     570                 :            : 
     571         [ #  # ]:          0 :         if (!d)
     572                 :          0 :                 return log_oom();
     573                 :            : 
     574                 :          0 :         *ret_badness = b;
     575                 :          0 :         *ret_description = d;
     576                 :            : 
     577                 :          0 :         return 0;
     578                 :            : }
     579                 :            : 
     580                 :            : #endif
     581                 :            : 
     582                 :          0 : static int assess_ip_address_allow(
     583                 :            :                 const struct security_assessor *a,
     584                 :            :                 const struct security_info *info,
     585                 :            :                 const void *data,
     586                 :            :                 uint64_t *ret_badness,
     587                 :            :                 char **ret_description) {
     588                 :            : 
     589                 :          0 :         char *d = NULL;
     590                 :            :         uint64_t b;
     591                 :            : 
     592         [ #  # ]:          0 :         assert(info);
     593         [ #  # ]:          0 :         assert(ret_badness);
     594         [ #  # ]:          0 :         assert(ret_description);
     595                 :            : 
     596   [ #  #  #  # ]:          0 :         if (info->ip_filters_custom_ingress || info->ip_filters_custom_egress) {
     597                 :          0 :                 d = strdup("Service defines custom ingress/egress IP filters with BPF programs");
     598                 :          0 :                 b = 0;
     599         [ #  # ]:          0 :         } else if (!info->ip_address_deny_all) {
     600                 :          0 :                 d = strdup("Service does not define an IP address whitelist");
     601                 :          0 :                 b = 10;
     602         [ #  # ]:          0 :         } else if (info->ip_address_allow_other) {
     603                 :          0 :                 d = strdup("Service defines IP address whitelist with non-localhost entries");
     604                 :          0 :                 b = 5;
     605         [ #  # ]:          0 :         } else if (info->ip_address_allow_localhost) {
     606                 :          0 :                 d = strdup("Service defines IP address whitelist with only localhost entries");
     607                 :          0 :                 b = 2;
     608                 :            :         } else {
     609                 :          0 :                 d = strdup("Service blocks all IP address ranges");
     610                 :          0 :                 b = 0;
     611                 :            :         }
     612                 :            : 
     613         [ #  # ]:          0 :         if (!d)
     614                 :          0 :                 return log_oom();
     615                 :            : 
     616                 :          0 :         *ret_badness = b;
     617                 :          0 :         *ret_description = d;
     618                 :            : 
     619                 :          0 :         return 0;
     620                 :            : }
     621                 :            : 
     622                 :          0 : static int assess_device_allow(
     623                 :            :                 const struct security_assessor *a,
     624                 :            :                 const struct security_info *info,
     625                 :            :                 const void *data,
     626                 :            :                 uint64_t *ret_badness,
     627                 :            :                 char **ret_description) {
     628                 :            : 
     629                 :          0 :         char *d = NULL;
     630                 :            :         uint64_t b;
     631                 :            : 
     632         [ #  # ]:          0 :         assert(info);
     633         [ #  # ]:          0 :         assert(ret_badness);
     634         [ #  # ]:          0 :         assert(ret_description);
     635                 :            : 
     636   [ #  #  #  #  :          0 :         if (STRPTR_IN_SET(info->device_policy, "strict", "closed")) {
                   #  # ]
     637                 :            : 
     638         [ #  # ]:          0 :                 if (info->device_allow_non_empty) {
     639                 :          0 :                         d = strdup("Service has a device ACL with some special devices");
     640                 :          0 :                         b = 5;
     641                 :            :                 } else {
     642                 :          0 :                         d = strdup("Service has a minimal device ACL");
     643                 :          0 :                         b = 0;
     644                 :            :                 }
     645                 :            :         } else {
     646                 :          0 :                 d = strdup("Service has no device ACL");
     647                 :          0 :                 b = 10;
     648                 :            :         }
     649                 :            : 
     650         [ #  # ]:          0 :         if (!d)
     651                 :          0 :                 return log_oom();
     652                 :            : 
     653                 :          0 :         *ret_badness = b;
     654                 :          0 :         *ret_description = d;
     655                 :            : 
     656                 :          0 :         return 0;
     657                 :            : }
     658                 :            : 
     659                 :          0 : static int assess_ambient_capabilities(
     660                 :            :                 const struct security_assessor *a,
     661                 :            :                 const struct security_info *info,
     662                 :            :                 const void *data,
     663                 :            :                 uint64_t *ret_badness,
     664                 :            :                 char **ret_description) {
     665                 :            : 
     666         [ #  # ]:          0 :         assert(ret_badness);
     667         [ #  # ]:          0 :         assert(ret_description);
     668                 :            : 
     669                 :          0 :         *ret_badness = info->ambient_capabilities != 0;
     670                 :          0 :         *ret_description = NULL;
     671                 :            : 
     672                 :          0 :         return 0;
     673                 :            : }
     674                 :            : 
     675                 :            : static const struct security_assessor security_assessor_table[] = {
     676                 :            :         {
     677                 :            :                 .id = "User=/DynamicUser=",
     678                 :            :                 .description_bad = "Service runs as root user",
     679                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#User=",
     680                 :            :                 .weight = 2000,
     681                 :            :                 .range = 10,
     682                 :            :                 .assess = assess_user,
     683                 :            :         },
     684                 :            :         {
     685                 :            :                 .id = "SupplementaryGroups=",
     686                 :            :                 .description_good = "Service has no supplementary groups",
     687                 :            :                 .description_bad = "Service runs with supplementary groups",
     688                 :            :                 .description_na = "Service runs as root, option does not matter",
     689                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SupplementaryGroups=",
     690                 :            :                 .weight = 200,
     691                 :            :                 .range = 1,
     692                 :            :                 .assess = assess_supplementary_groups,
     693                 :            :         },
     694                 :            :         {
     695                 :            :                 .id = "PrivateDevices=",
     696                 :            :                 .description_good = "Service has no access to hardware devices",
     697                 :            :                 .description_bad = "Service potentially has access to hardware devices",
     698                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices=",
     699                 :            :                 .weight = 1000,
     700                 :            :                 .range = 1,
     701                 :            :                 .assess = assess_bool,
     702                 :            :                 .offset = offsetof(struct security_info, private_devices),
     703                 :            :         },
     704                 :            :         {
     705                 :            :                 .id = "PrivateMounts=",
     706                 :            :                 .description_good = "Service cannot install system mounts",
     707                 :            :                 .description_bad = "Service may install system mounts",
     708                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateMounts=",
     709                 :            :                 .weight = 1000,
     710                 :            :                 .range = 1,
     711                 :            :                 .assess = assess_bool,
     712                 :            :                 .offset = offsetof(struct security_info, private_mounts),
     713                 :            :         },
     714                 :            :         {
     715                 :            :                 .id = "PrivateNetwork=",
     716                 :            :                 .description_good = "Service has no access to the host's network",
     717                 :            :                 .description_bad = "Service has access to the host's network",
     718                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateNetwork=",
     719                 :            :                 .weight = 2500,
     720                 :            :                 .range = 1,
     721                 :            :                 .assess = assess_bool,
     722                 :            :                 .offset = offsetof(struct security_info, private_network),
     723                 :            :         },
     724                 :            :         {
     725                 :            :                 .id = "PrivateTmp=",
     726                 :            :                 .description_good = "Service has no access to other software's temporary files",
     727                 :            :                 .description_bad = "Service has access to other software's temporary files",
     728                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=",
     729                 :            :                 .weight = 1000,
     730                 :            :                 .range = 1,
     731                 :            :                 .assess = assess_bool,
     732                 :            :                 .offset = offsetof(struct security_info, private_tmp),
     733                 :            :                 .default_dependencies_only = true,
     734                 :            :         },
     735                 :            :         {
     736                 :            :                 .id = "PrivateUsers=",
     737                 :            :                 .description_good = "Service does not have access to other users",
     738                 :            :                 .description_bad = "Service has access to other users",
     739                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateUsers=",
     740                 :            :                 .weight = 1000,
     741                 :            :                 .range = 1,
     742                 :            :                 .assess = assess_bool,
     743                 :            :                 .offset = offsetof(struct security_info, private_users),
     744                 :            :         },
     745                 :            :         {
     746                 :            :                 .id = "ProtectControlGroups=",
     747                 :            :                 .description_good = "Service cannot modify the control group file system",
     748                 :            :                 .description_bad = "Service may modify to the control group file system",
     749                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectControlGroups=",
     750                 :            :                 .weight = 1000,
     751                 :            :                 .range = 1,
     752                 :            :                 .assess = assess_bool,
     753                 :            :                 .offset = offsetof(struct security_info, protect_control_groups),
     754                 :            :         },
     755                 :            :         {
     756                 :            :                 .id = "ProtectKernelModules=",
     757                 :            :                 .description_good = "Service cannot load or read kernel modules",
     758                 :            :                 .description_bad = "Service may load or read kernel modules",
     759                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelModules=",
     760                 :            :                 .weight = 1000,
     761                 :            :                 .range = 1,
     762                 :            :                 .assess = assess_bool,
     763                 :            :                 .offset = offsetof(struct security_info, protect_kernel_modules),
     764                 :            :         },
     765                 :            :         {
     766                 :            :                 .id = "ProtectKernelTunables=",
     767                 :            :                 .description_good = "Service cannot alter kernel tunables (/proc/sys, …)",
     768                 :            :                 .description_bad = "Service may alter kernel tunables",
     769                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectKernelTunables=",
     770                 :            :                 .weight = 1000,
     771                 :            :                 .range = 1,
     772                 :            :                 .assess = assess_bool,
     773                 :            :                 .offset = offsetof(struct security_info, protect_kernel_tunables),
     774                 :            :         },
     775                 :            :         {
     776                 :            :                 .id = "ProtectHome=",
     777                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHome=",
     778                 :            :                 .weight = 1000,
     779                 :            :                 .range = 10,
     780                 :            :                 .assess = assess_protect_home,
     781                 :            :                 .default_dependencies_only = true,
     782                 :            :         },
     783                 :            :         {
     784                 :            :                 .id = "ProtectHostname=",
     785                 :            :                 .description_good = "Service cannot change system host/domainname",
     786                 :            :                 .description_bad = "Service may change system host/domainname",
     787                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectHostname=",
     788                 :            :                 .weight = 50,
     789                 :            :                 .range = 1,
     790                 :            :                 .assess = assess_bool,
     791                 :            :                 .offset = offsetof(struct security_info, protect_hostname),
     792                 :            :         },
     793                 :            :         {
     794                 :            :                 .id = "ProtectSystem=",
     795                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem=",
     796                 :            :                 .weight = 1000,
     797                 :            :                 .range = 10,
     798                 :            :                 .assess = assess_protect_system,
     799                 :            :                 .default_dependencies_only = true,
     800                 :            :         },
     801                 :            :         {
     802                 :            :                 .id = "RootDirectory=/RootImage=",
     803                 :            :                 .description_good = "Service has its own root directory/image",
     804                 :            :                 .description_bad = "Service runs within the host's root directory",
     805                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RootDirectory=",
     806                 :            :                 .weight = 200,
     807                 :            :                 .range = 1,
     808                 :            :                 .assess = assess_root_directory,
     809                 :            :                 .default_dependencies_only = true,
     810                 :            :         },
     811                 :            :         {
     812                 :            :                 .id = "LockPersonality=",
     813                 :            :                 .description_good = "Service cannot change ABI personality",
     814                 :            :                 .description_bad = "Service may change ABI personality",
     815                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#LockPersonality=",
     816                 :            :                 .weight = 100,
     817                 :            :                 .range = 1,
     818                 :            :                 .assess = assess_bool,
     819                 :            :                 .offset = offsetof(struct security_info, lock_personality),
     820                 :            :         },
     821                 :            :         {
     822                 :            :                 .id = "MemoryDenyWriteExecute=",
     823                 :            :                 .description_good = "Service cannot create writable executable memory mappings",
     824                 :            :                 .description_bad = "Service may create writable executable memory mappings",
     825                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#MemoryDenyWriteExecute=",
     826                 :            :                 .weight = 100,
     827                 :            :                 .range = 1,
     828                 :            :                 .assess = assess_bool,
     829                 :            :                 .offset = offsetof(struct security_info, memory_deny_write_execute),
     830                 :            :         },
     831                 :            :         {
     832                 :            :                 .id = "NoNewPrivileges=",
     833                 :            :                 .description_good = "Service processes cannot acquire new privileges",
     834                 :            :                 .description_bad = "Service processes may acquire new privileges",
     835                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges=",
     836                 :            :                 .weight = 1000,
     837                 :            :                 .range = 1,
     838                 :            :                 .assess = assess_bool,
     839                 :            :                 .offset = offsetof(struct security_info, no_new_privileges),
     840                 :            :         },
     841                 :            :         {
     842                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_ADMIN",
     843                 :            :                 .description_good = "Service has no administrator privileges",
     844                 :            :                 .description_bad = "Service has administrator privileges",
     845                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     846                 :            :                 .weight = 1500,
     847                 :            :                 .range = 1,
     848                 :            :                 .assess = assess_capability_bounding_set,
     849                 :            :                 .parameter = UINT64_C(1) << CAP_SYS_ADMIN,
     850                 :            :         },
     851                 :            :         {
     852                 :            :                 .id = "CapabilityBoundingSet=~CAP_SET(UID|GID|PCAP)",
     853                 :            :                 .description_good = "Service cannot change UID/GID identities/capabilities",
     854                 :            :                 .description_bad = "Service may change UID/GID identities/capabilities",
     855                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     856                 :            :                 .weight = 1500,
     857                 :            :                 .range = 1,
     858                 :            :                 .assess = assess_capability_bounding_set,
     859                 :            :                 .parameter = (UINT64_C(1) << CAP_SETUID)|
     860                 :            :                              (UINT64_C(1) << CAP_SETGID)|
     861                 :            :                              (UINT64_C(1) << CAP_SETPCAP),
     862                 :            :         },
     863                 :            :         {
     864                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_PTRACE",
     865                 :            :                 .description_good = "Service has no ptrace() debugging abilities",
     866                 :            :                 .description_bad = "Service has ptrace() debugging abilities",
     867                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     868                 :            :                 .weight = 1500,
     869                 :            :                 .range = 1,
     870                 :            :                 .assess = assess_capability_bounding_set,
     871                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_PTRACE),
     872                 :            :         },
     873                 :            :         {
     874                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_TIME",
     875                 :            :                 .description_good = "Service processes cannot change the system clock",
     876                 :            :                 .description_bad = "Service processes may change the system clock",
     877                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     878                 :            :                 .weight = 1000,
     879                 :            :                 .range = 1,
     880                 :            :                 .assess = assess_capability_bounding_set,
     881                 :            :                 .parameter = UINT64_C(1) << CAP_SYS_TIME,
     882                 :            :         },
     883                 :            :         {
     884                 :            :                 .id = "CapabilityBoundingSet=~CAP_NET_ADMIN",
     885                 :            :                 .description_good = "Service has no network configuration privileges",
     886                 :            :                 .description_bad = "Service has network configuration privileges",
     887                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     888                 :            :                 .weight = 1000,
     889                 :            :                 .range = 1,
     890                 :            :                 .assess = assess_capability_bounding_set,
     891                 :            :                 .parameter = (UINT64_C(1) << CAP_NET_ADMIN),
     892                 :            :         },
     893                 :            :         {
     894                 :            :                 .id = "CapabilityBoundingSet=~CAP_RAWIO",
     895                 :            :                 .description_good = "Service has no raw I/O access",
     896                 :            :                 .description_bad = "Service has raw I/O access",
     897                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     898                 :            :                 .weight = 1000,
     899                 :            :                 .range = 1,
     900                 :            :                 .assess = assess_capability_bounding_set,
     901                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_RAWIO),
     902                 :            :         },
     903                 :            :         {
     904                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_MODULE",
     905                 :            :                 .description_good = "Service cannot load kernel modules",
     906                 :            :                 .description_bad = "Service may load kernel modules",
     907                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     908                 :            :                 .weight = 1000,
     909                 :            :                 .range = 1,
     910                 :            :                 .assess = assess_capability_bounding_set,
     911                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_MODULE),
     912                 :            :         },
     913                 :            :         {
     914                 :            :                 .id = "CapabilityBoundingSet=~CAP_AUDIT_*",
     915                 :            :                 .description_good = "Service has no audit subsystem access",
     916                 :            :                 .description_bad = "Service has audit subsystem access",
     917                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     918                 :            :                 .weight = 500,
     919                 :            :                 .range = 1,
     920                 :            :                 .assess = assess_capability_bounding_set,
     921                 :            :                 .parameter = (UINT64_C(1) << CAP_AUDIT_CONTROL) |
     922                 :            :                              (UINT64_C(1) << CAP_AUDIT_READ) |
     923                 :            :                              (UINT64_C(1) << CAP_AUDIT_WRITE),
     924                 :            :         },
     925                 :            :         {
     926                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYSLOG",
     927                 :            :                 .description_good = "Service has no access to kernel logging",
     928                 :            :                 .description_bad = "Service has access to kernel logging",
     929                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     930                 :            :                 .weight = 500,
     931                 :            :                 .range = 1,
     932                 :            :                 .assess = assess_capability_bounding_set,
     933                 :            :                 .parameter = (UINT64_C(1) << CAP_SYSLOG),
     934                 :            :         },
     935                 :            :         {
     936                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_(NICE|RESOURCE)",
     937                 :            :                 .description_good = "Service has no privileges to change resource use parameters",
     938                 :            :                 .description_bad = "Service has privileges to change resource use parameters",
     939                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     940                 :            :                 .weight = 500,
     941                 :            :                 .range = 1,
     942                 :            :                 .assess = assess_capability_bounding_set,
     943                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_NICE) |
     944                 :            :                              (UINT64_C(1) << CAP_SYS_RESOURCE),
     945                 :            :         },
     946                 :            :         {
     947                 :            :                 .id = "CapabilityBoundingSet=~CAP_MKNOD",
     948                 :            :                 .description_good = "Service cannot create device nodes",
     949                 :            :                 .description_bad = "Service may create device nodes",
     950                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     951                 :            :                 .weight = 500,
     952                 :            :                 .range = 1,
     953                 :            :                 .assess = assess_capability_bounding_set,
     954                 :            :                 .parameter = (UINT64_C(1) << CAP_MKNOD),
     955                 :            :         },
     956                 :            :         {
     957                 :            :                 .id = "CapabilityBoundingSet=~CAP_(CHOWN|FSETID|SETFCAP)",
     958                 :            :                 .description_good = "Service cannot change file ownership/access mode/capabilities",
     959                 :            :                 .description_bad = "Service may change file ownership/access mode/capabilities unrestricted",
     960                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     961                 :            :                 .weight = 1000,
     962                 :            :                 .range = 1,
     963                 :            :                 .assess = assess_capability_bounding_set,
     964                 :            :                 .parameter = (UINT64_C(1) << CAP_CHOWN) |
     965                 :            :                              (UINT64_C(1) << CAP_FSETID) |
     966                 :            :                              (UINT64_C(1) << CAP_SETFCAP),
     967                 :            :         },
     968                 :            :         {
     969                 :            :                 .id = "CapabilityBoundingSet=~CAP_(DAC_*|FOWNER|IPC_OWNER)",
     970                 :            :                 .description_good = "Service cannot override UNIX file/IPC permission checks",
     971                 :            :                 .description_bad = "Service may override UNIX file/IPC permission checks",
     972                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     973                 :            :                 .weight = 1000,
     974                 :            :                 .range = 1,
     975                 :            :                 .assess = assess_capability_bounding_set,
     976                 :            :                 .parameter = (UINT64_C(1) << CAP_DAC_OVERRIDE) |
     977                 :            :                              (UINT64_C(1) << CAP_DAC_READ_SEARCH) |
     978                 :            :                              (UINT64_C(1) << CAP_FOWNER) |
     979                 :            :                              (UINT64_C(1) << CAP_IPC_OWNER),
     980                 :            :         },
     981                 :            :         {
     982                 :            :                 .id = "CapabilityBoundingSet=~CAP_KILL",
     983                 :            :                 .description_good = "Service cannot send UNIX signals to arbitrary processes",
     984                 :            :                 .description_bad = "Service may send UNIX signals to arbitrary processes",
     985                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     986                 :            :                 .weight = 500,
     987                 :            :                 .range = 1,
     988                 :            :                 .assess = assess_capability_bounding_set,
     989                 :            :                 .parameter = (UINT64_C(1) << CAP_KILL),
     990                 :            :         },
     991                 :            :         {
     992                 :            :                 .id = "CapabilityBoundingSet=~CAP_NET_(BIND_SERVICE|BROADCAST|RAW)",
     993                 :            :                 .description_good = "Service has no elevated networking privileges",
     994                 :            :                 .description_bad = "Service has elevated networking privileges",
     995                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
     996                 :            :                 .weight = 500,
     997                 :            :                 .range = 1,
     998                 :            :                 .assess = assess_capability_bounding_set,
     999                 :            :                 .parameter = (UINT64_C(1) << CAP_NET_BIND_SERVICE) |
    1000                 :            :                              (UINT64_C(1) << CAP_NET_BROADCAST) |
    1001                 :            :                              (UINT64_C(1) << CAP_NET_RAW),
    1002                 :            :         },
    1003                 :            :         {
    1004                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_BOOT",
    1005                 :            :                 .description_good = "Service cannot issue reboot()",
    1006                 :            :                 .description_bad = "Service may issue reboot()",
    1007                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1008                 :            :                 .weight = 100,
    1009                 :            :                 .range = 1,
    1010                 :            :                 .assess = assess_capability_bounding_set,
    1011                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_BOOT),
    1012                 :            :         },
    1013                 :            :         {
    1014                 :            :                 .id = "CapabilityBoundingSet=~CAP_MAC_*",
    1015                 :            :                 .description_good = "Service cannot adjust SMACK MAC",
    1016                 :            :                 .description_bad = "Service may adjust SMACK MAC",
    1017                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1018                 :            :                 .weight = 100,
    1019                 :            :                 .range = 1,
    1020                 :            :                 .assess = assess_capability_bounding_set,
    1021                 :            :                 .parameter = (UINT64_C(1) << CAP_MAC_ADMIN)|
    1022                 :            :                              (UINT64_C(1) << CAP_MAC_OVERRIDE),
    1023                 :            :         },
    1024                 :            :         {
    1025                 :            :                 .id = "CapabilityBoundingSet=~CAP_LINUX_IMMUTABLE",
    1026                 :            :                 .description_good = "Service cannot mark files immutable",
    1027                 :            :                 .description_bad = "Service may mark files immutable",
    1028                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1029                 :            :                 .weight = 75,
    1030                 :            :                 .range = 1,
    1031                 :            :                 .assess = assess_capability_bounding_set,
    1032                 :            :                 .parameter = (UINT64_C(1) << CAP_LINUX_IMMUTABLE),
    1033                 :            :         },
    1034                 :            :         {
    1035                 :            :                 .id = "CapabilityBoundingSet=~CAP_IPC_LOCK",
    1036                 :            :                 .description_good = "Service cannot lock memory into RAM",
    1037                 :            :                 .description_bad = "Service may lock memory into RAM",
    1038                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1039                 :            :                 .weight = 50,
    1040                 :            :                 .range = 1,
    1041                 :            :                 .assess = assess_capability_bounding_set,
    1042                 :            :                 .parameter = (UINT64_C(1) << CAP_IPC_LOCK),
    1043                 :            :         },
    1044                 :            :         {
    1045                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_CHROOT",
    1046                 :            :                 .description_good = "Service cannot issue chroot()",
    1047                 :            :                 .description_bad = "Service may issue chroot()",
    1048                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1049                 :            :                 .weight = 50,
    1050                 :            :                 .range = 1,
    1051                 :            :                 .assess = assess_capability_bounding_set,
    1052                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_CHROOT),
    1053                 :            :         },
    1054                 :            :         {
    1055                 :            :                 .id = "CapabilityBoundingSet=~CAP_BLOCK_SUSPEND",
    1056                 :            :                 .description_good = "Service cannot establish wake locks",
    1057                 :            :                 .description_bad = "Service may establish wake locks",
    1058                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1059                 :            :                 .weight = 25,
    1060                 :            :                 .range = 1,
    1061                 :            :                 .assess = assess_capability_bounding_set,
    1062                 :            :                 .parameter = (UINT64_C(1) << CAP_BLOCK_SUSPEND),
    1063                 :            :         },
    1064                 :            :         {
    1065                 :            :                 .id = "CapabilityBoundingSet=~CAP_WAKE_ALARM",
    1066                 :            :                 .description_good = "Service cannot program timers that wake up the system",
    1067                 :            :                 .description_bad = "Service may program timers that wake up the system",
    1068                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1069                 :            :                 .weight = 25,
    1070                 :            :                 .range = 1,
    1071                 :            :                 .assess = assess_capability_bounding_set,
    1072                 :            :                 .parameter = (UINT64_C(1) << CAP_WAKE_ALARM),
    1073                 :            :         },
    1074                 :            :         {
    1075                 :            :                 .id = "CapabilityBoundingSet=~CAP_LEASE",
    1076                 :            :                 .description_good = "Service cannot create file leases",
    1077                 :            :                 .description_bad = "Service may create file leases",
    1078                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1079                 :            :                 .weight = 25,
    1080                 :            :                 .range = 1,
    1081                 :            :                 .assess = assess_capability_bounding_set,
    1082                 :            :                 .parameter = (UINT64_C(1) << CAP_LEASE),
    1083                 :            :         },
    1084                 :            :         {
    1085                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_TTY_CONFIG",
    1086                 :            :                 .description_good = "Service cannot issue vhangup()",
    1087                 :            :                 .description_bad = "Service may issue vhangup()",
    1088                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1089                 :            :                 .weight = 25,
    1090                 :            :                 .range = 1,
    1091                 :            :                 .assess = assess_capability_bounding_set,
    1092                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_TTY_CONFIG),
    1093                 :            :         },
    1094                 :            :         {
    1095                 :            :                 .id = "CapabilityBoundingSet=~CAP_SYS_PACCT",
    1096                 :            :                 .description_good = "Service cannot use acct()",
    1097                 :            :                 .description_bad = "Service may use acct()",
    1098                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#CapabilityBoundingSet=",
    1099                 :            :                 .weight = 25,
    1100                 :            :                 .range = 1,
    1101                 :            :                 .assess = assess_capability_bounding_set,
    1102                 :            :                 .parameter = (UINT64_C(1) << CAP_SYS_PACCT),
    1103                 :            :         },
    1104                 :            :         {
    1105                 :            :                 .id = "UMask=",
    1106                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#UMask=",
    1107                 :            :                 .weight = 100,
    1108                 :            :                 .range = 10,
    1109                 :            :                 .assess = assess_umask,
    1110                 :            :         },
    1111                 :            :         {
    1112                 :            :                 .id = "KeyringMode=",
    1113                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#KeyringMode=",
    1114                 :            :                 .description_good = "Service doesn't share key material with other services",
    1115                 :            :                 .description_bad = "Service shares key material with other service",
    1116                 :            :                 .weight = 1000,
    1117                 :            :                 .range = 1,
    1118                 :            :                 .assess = assess_keyring_mode,
    1119                 :            :         },
    1120                 :            :         {
    1121                 :            :                 .id = "NotifyAccess=",
    1122                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NotifyAccess=",
    1123                 :            :                 .description_good = "Service child processes cannot alter service state",
    1124                 :            :                 .description_bad = "Service child processes may alter service state",
    1125                 :            :                 .weight = 1000,
    1126                 :            :                 .range = 1,
    1127                 :            :                 .assess = assess_notify_access,
    1128                 :            :         },
    1129                 :            :         {
    1130                 :            :                 .id = "RemoveIPC=",
    1131                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RemoveIPC=",
    1132                 :            :                 .description_good = "Service user cannot leave SysV IPC objects around",
    1133                 :            :                 .description_bad = "Service user may leave SysV IPC objects around",
    1134                 :            :                 .description_na = "Service runs as root, option does not apply",
    1135                 :            :                 .weight = 100,
    1136                 :            :                 .range = 1,
    1137                 :            :                 .assess = assess_remove_ipc,
    1138                 :            :                 .offset = offsetof(struct security_info, remove_ipc),
    1139                 :            :         },
    1140                 :            :         {
    1141                 :            :                 .id = "Delegate=",
    1142                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#Delegate=",
    1143                 :            :                 .description_good = "Service does not maintain its own delegated control group subtree",
    1144                 :            :                 .description_bad = "Service maintains its own delegated control group subtree",
    1145                 :            :                 .weight = 100,
    1146                 :            :                 .range = 1,
    1147                 :            :                 .assess = assess_bool,
    1148                 :            :                 .offset = offsetof(struct security_info, delegate),
    1149                 :            :                 .parameter = true, /* invert! */
    1150                 :            :         },
    1151                 :            :         {
    1152                 :            :                 .id = "RestrictRealtime=",
    1153                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictRealtime=",
    1154                 :            :                 .description_good = "Service realtime scheduling access is restricted",
    1155                 :            :                 .description_bad = "Service may acquire realtime scheduling",
    1156                 :            :                 .weight = 500,
    1157                 :            :                 .range = 1,
    1158                 :            :                 .assess = assess_bool,
    1159                 :            :                 .offset = offsetof(struct security_info, restrict_realtime),
    1160                 :            :         },
    1161                 :            :         {
    1162                 :            :                 .id = "RestrictSUIDSGID=",
    1163                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictSUIDSGID=",
    1164                 :            :                 .description_good = "SUID/SGID file creation by service is restricted",
    1165                 :            :                 .description_bad = "Service may create SUID/SGID files",
    1166                 :            :                 .weight = 1000,
    1167                 :            :                 .range = 1,
    1168                 :            :                 .assess = assess_bool,
    1169                 :            :                 .offset = offsetof(struct security_info, restrict_suid_sgid),
    1170                 :            :         },
    1171                 :            :         {
    1172                 :            :                 .id = "RestrictNamespaces=~CLONE_NEWUSER",
    1173                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
    1174                 :            :                 .description_good = "Service cannot create user namespaces",
    1175                 :            :                 .description_bad = "Service may create user namespaces",
    1176                 :            :                 .weight = 1500,
    1177                 :            :                 .range = 1,
    1178                 :            :                 .assess = assess_restrict_namespaces,
    1179                 :            :                 .parameter = CLONE_NEWUSER,
    1180                 :            :         },
    1181                 :            :         {
    1182                 :            :                 .id = "RestrictNamespaces=~CLONE_NEWNS",
    1183                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
    1184                 :            :                 .description_good = "Service cannot create file system namespaces",
    1185                 :            :                 .description_bad = "Service may create file system namespaces",
    1186                 :            :                 .weight = 500,
    1187                 :            :                 .range = 1,
    1188                 :            :                 .assess = assess_restrict_namespaces,
    1189                 :            :                 .parameter = CLONE_NEWNS,
    1190                 :            :         },
    1191                 :            :         {
    1192                 :            :                 .id = "RestrictNamespaces=~CLONE_NEWIPC",
    1193                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
    1194                 :            :                 .description_good = "Service cannot create IPC namespaces",
    1195                 :            :                 .description_bad = "Service may create IPC namespaces",
    1196                 :            :                 .weight = 500,
    1197                 :            :                 .range = 1,
    1198                 :            :                 .assess = assess_restrict_namespaces,
    1199                 :            :                 .parameter = CLONE_NEWIPC,
    1200                 :            :         },
    1201                 :            :         {
    1202                 :            :                 .id = "RestrictNamespaces=~CLONE_NEWPID",
    1203                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
    1204                 :            :                 .description_good = "Service cannot create process namespaces",
    1205                 :            :                 .description_bad = "Service may create process namespaces",
    1206                 :            :                 .weight = 500,
    1207                 :            :                 .range = 1,
    1208                 :            :                 .assess = assess_restrict_namespaces,
    1209                 :            :                 .parameter = CLONE_NEWPID,
    1210                 :            :         },
    1211                 :            :         {
    1212                 :            :                 .id = "RestrictNamespaces=~CLONE_NEWCGROUP",
    1213                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
    1214                 :            :                 .description_good = "Service cannot create cgroup namespaces",
    1215                 :            :                 .description_bad = "Service may create cgroup namespaces",
    1216                 :            :                 .weight = 500,
    1217                 :            :                 .range = 1,
    1218                 :            :                 .assess = assess_restrict_namespaces,
    1219                 :            :                 .parameter = CLONE_NEWCGROUP,
    1220                 :            :         },
    1221                 :            :         {
    1222                 :            :                 .id = "RestrictNamespaces=~CLONE_NEWNET",
    1223                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
    1224                 :            :                 .description_good = "Service cannot create network namespaces",
    1225                 :            :                 .description_bad = "Service may create network namespaces",
    1226                 :            :                 .weight = 500,
    1227                 :            :                 .range = 1,
    1228                 :            :                 .assess = assess_restrict_namespaces,
    1229                 :            :                 .parameter = CLONE_NEWNET,
    1230                 :            :         },
    1231                 :            :         {
    1232                 :            :                 .id = "RestrictNamespaces=~CLONE_NEWUTS",
    1233                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictNamespaces=",
    1234                 :            :                 .description_good = "Service cannot create hostname namespaces",
    1235                 :            :                 .description_bad = "Service may create hostname namespaces",
    1236                 :            :                 .weight = 100,
    1237                 :            :                 .range = 1,
    1238                 :            :                 .assess = assess_restrict_namespaces,
    1239                 :            :                 .parameter = CLONE_NEWUTS,
    1240                 :            :         },
    1241                 :            :         {
    1242                 :            :                 .id = "RestrictAddressFamilies=~AF_(INET|INET6)",
    1243                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
    1244                 :            :                 .description_good = "Service cannot allocate Internet sockets",
    1245                 :            :                 .description_bad = "Service may allocate Internet sockets",
    1246                 :            :                 .weight = 1500,
    1247                 :            :                 .range = 1,
    1248                 :            :                 .assess = assess_bool,
    1249                 :            :                 .offset = offsetof(struct security_info, restrict_address_family_inet),
    1250                 :            :         },
    1251                 :            :         {
    1252                 :            :                 .id = "RestrictAddressFamilies=~AF_UNIX",
    1253                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
    1254                 :            :                 .description_good = "Service cannot allocate local sockets",
    1255                 :            :                 .description_bad = "Service may allocate local sockets",
    1256                 :            :                 .weight = 25,
    1257                 :            :                 .range = 1,
    1258                 :            :                 .assess = assess_bool,
    1259                 :            :                 .offset = offsetof(struct security_info, restrict_address_family_unix),
    1260                 :            :         },
    1261                 :            :         {
    1262                 :            :                 .id = "RestrictAddressFamilies=~AF_NETLINK",
    1263                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
    1264                 :            :                 .description_good = "Service cannot allocate netlink sockets",
    1265                 :            :                 .description_bad = "Service may allocate netlink sockets",
    1266                 :            :                 .weight = 200,
    1267                 :            :                 .range = 1,
    1268                 :            :                 .assess = assess_bool,
    1269                 :            :                 .offset = offsetof(struct security_info, restrict_address_family_netlink),
    1270                 :            :         },
    1271                 :            :         {
    1272                 :            :                 .id = "RestrictAddressFamilies=~AF_PACKET",
    1273                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
    1274                 :            :                 .description_good = "Service cannot allocate packet sockets",
    1275                 :            :                 .description_bad = "Service may allocate packet sockets",
    1276                 :            :                 .weight = 1000,
    1277                 :            :                 .range = 1,
    1278                 :            :                 .assess = assess_bool,
    1279                 :            :                 .offset = offsetof(struct security_info, restrict_address_family_packet),
    1280                 :            :         },
    1281                 :            :         {
    1282                 :            :                 .id = "RestrictAddressFamilies=~…",
    1283                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RestrictAddressFamilies=",
    1284                 :            :                 .description_good = "Service cannot allocate exotic sockets",
    1285                 :            :                 .description_bad = "Service may allocate exotic sockets",
    1286                 :            :                 .weight = 1250,
    1287                 :            :                 .range = 1,
    1288                 :            :                 .assess = assess_bool,
    1289                 :            :                 .offset = offsetof(struct security_info, restrict_address_family_other),
    1290                 :            :         },
    1291                 :            :         {
    1292                 :            :                 .id = "SystemCallArchitectures=",
    1293                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallArchitectures=",
    1294                 :            :                 .weight = 1000,
    1295                 :            :                 .range = 10,
    1296                 :            :                 .assess = assess_system_call_architectures,
    1297                 :            :         },
    1298                 :            : #if HAVE_SECCOMP
    1299                 :            :         {
    1300                 :            :                 .id = "SystemCallFilter=~@swap",
    1301                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1302                 :            :                 .weight = 1000,
    1303                 :            :                 .range = 10,
    1304                 :            :                 .assess = assess_system_call_filter,
    1305                 :            :                 .parameter = SYSCALL_FILTER_SET_SWAP,
    1306                 :            :         },
    1307                 :            :         {
    1308                 :            :                 .id = "SystemCallFilter=~@obsolete",
    1309                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1310                 :            :                 .weight = 250,
    1311                 :            :                 .range = 10,
    1312                 :            :                 .assess = assess_system_call_filter,
    1313                 :            :                 .parameter = SYSCALL_FILTER_SET_OBSOLETE,
    1314                 :            :         },
    1315                 :            :         {
    1316                 :            :                 .id = "SystemCallFilter=~@clock",
    1317                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1318                 :            :                 .weight = 1000,
    1319                 :            :                 .range = 10,
    1320                 :            :                 .assess = assess_system_call_filter,
    1321                 :            :                 .parameter = SYSCALL_FILTER_SET_CLOCK,
    1322                 :            :         },
    1323                 :            :         {
    1324                 :            :                 .id = "SystemCallFilter=~@cpu-emulation",
    1325                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1326                 :            :                 .weight = 250,
    1327                 :            :                 .range = 10,
    1328                 :            :                 .assess = assess_system_call_filter,
    1329                 :            :                 .parameter = SYSCALL_FILTER_SET_CPU_EMULATION,
    1330                 :            :         },
    1331                 :            :         {
    1332                 :            :                 .id = "SystemCallFilter=~@debug",
    1333                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1334                 :            :                 .weight = 1000,
    1335                 :            :                 .range = 10,
    1336                 :            :                 .assess = assess_system_call_filter,
    1337                 :            :                 .parameter = SYSCALL_FILTER_SET_DEBUG,
    1338                 :            :         },
    1339                 :            :         {
    1340                 :            :                 .id = "SystemCallFilter=~@mount",
    1341                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1342                 :            :                 .weight = 1000,
    1343                 :            :                 .range = 10,
    1344                 :            :                 .assess = assess_system_call_filter,
    1345                 :            :                 .parameter = SYSCALL_FILTER_SET_MOUNT,
    1346                 :            :         },
    1347                 :            :         {
    1348                 :            :                 .id = "SystemCallFilter=~@module",
    1349                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1350                 :            :                 .weight = 1000,
    1351                 :            :                 .range = 10,
    1352                 :            :                 .assess = assess_system_call_filter,
    1353                 :            :                 .parameter = SYSCALL_FILTER_SET_MODULE,
    1354                 :            :         },
    1355                 :            :         {
    1356                 :            :                 .id = "SystemCallFilter=~@raw-io",
    1357                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1358                 :            :                 .weight = 1000,
    1359                 :            :                 .range = 10,
    1360                 :            :                 .assess = assess_system_call_filter,
    1361                 :            :                 .parameter = SYSCALL_FILTER_SET_RAW_IO,
    1362                 :            :         },
    1363                 :            :         {
    1364                 :            :                 .id = "SystemCallFilter=~@reboot",
    1365                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1366                 :            :                 .weight = 1000,
    1367                 :            :                 .range = 10,
    1368                 :            :                 .assess = assess_system_call_filter,
    1369                 :            :                 .parameter = SYSCALL_FILTER_SET_REBOOT,
    1370                 :            :         },
    1371                 :            :         {
    1372                 :            :                 .id = "SystemCallFilter=~@privileged",
    1373                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1374                 :            :                 .weight = 700,
    1375                 :            :                 .range = 10,
    1376                 :            :                 .assess = assess_system_call_filter,
    1377                 :            :                 .parameter = SYSCALL_FILTER_SET_PRIVILEGED,
    1378                 :            :         },
    1379                 :            :         {
    1380                 :            :                 .id = "SystemCallFilter=~@resources",
    1381                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#SystemCallFilter=",
    1382                 :            :                 .weight = 700,
    1383                 :            :                 .range = 10,
    1384                 :            :                 .assess = assess_system_call_filter,
    1385                 :            :                 .parameter = SYSCALL_FILTER_SET_RESOURCES,
    1386                 :            :         },
    1387                 :            : #endif
    1388                 :            :         {
    1389                 :            :                 .id = "IPAddressDeny=",
    1390                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#IPAddressDeny=",
    1391                 :            :                 .weight = 1000,
    1392                 :            :                 .range = 10,
    1393                 :            :                 .assess = assess_ip_address_allow,
    1394                 :            :         },
    1395                 :            :         {
    1396                 :            :                 .id = "DeviceAllow=",
    1397                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#DeviceAllow=",
    1398                 :            :                 .weight = 1000,
    1399                 :            :                 .range = 10,
    1400                 :            :                 .assess = assess_device_allow,
    1401                 :            :         },
    1402                 :            :         {
    1403                 :            :                 .id = "AmbientCapabilities=",
    1404                 :            :                 .url = "https://www.freedesktop.org/software/systemd/man/systemd.exec.html#AmbientCapabilities=",
    1405                 :            :                 .description_good = "Service process does not receive ambient capabilities",
    1406                 :            :                 .description_bad = "Service process receives ambient capabilities",
    1407                 :            :                 .weight = 500,
    1408                 :            :                 .range = 1,
    1409                 :            :                 .assess = assess_ambient_capabilities,
    1410                 :            :         },
    1411                 :            : };
    1412                 :            : 
    1413                 :          0 : static int assess(const struct security_info *info, Table *overview_table, AnalyzeSecurityFlags flags) {
    1414                 :            :         static const struct {
    1415                 :            :                 uint64_t exposure;
    1416                 :            :                 const char *name;
    1417                 :            :                 const char *color;
    1418                 :            :                 SpecialGlyph smiley;
    1419                 :            :         } badness_table[] = {
    1420                 :            :                 { 100, "DANGEROUS", ANSI_HIGHLIGHT_RED,    SPECIAL_GLYPH_DEPRESSED_SMILEY        },
    1421                 :            :                 { 90,  "UNSAFE",    ANSI_HIGHLIGHT_RED,    SPECIAL_GLYPH_UNHAPPY_SMILEY          },
    1422                 :            :                 { 75,  "EXPOSED",   ANSI_HIGHLIGHT_YELLOW, SPECIAL_GLYPH_SLIGHTLY_UNHAPPY_SMILEY },
    1423                 :            :                 { 50,  "MEDIUM",    NULL,                  SPECIAL_GLYPH_NEUTRAL_SMILEY          },
    1424                 :            :                 { 10,  "OK",        ANSI_HIGHLIGHT_GREEN,  SPECIAL_GLYPH_SLIGHTLY_HAPPY_SMILEY   },
    1425                 :            :                 { 1,   "SAFE",      ANSI_HIGHLIGHT_GREEN,  SPECIAL_GLYPH_HAPPY_SMILEY            },
    1426                 :            :                 { 0,   "PERFECT",   ANSI_HIGHLIGHT_GREEN,  SPECIAL_GLYPH_ECSTATIC_SMILEY         },
    1427                 :            :         };
    1428                 :            : 
    1429                 :          0 :         uint64_t badness_sum = 0, weight_sum = 0, exposure;
    1430                 :          0 :         _cleanup_(table_unrefp) Table *details_table = NULL;
    1431                 :            :         size_t i;
    1432                 :            :         int r;
    1433                 :            : 
    1434   [ #  #  #  # ]:          0 :         if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)) {
    1435                 :          0 :                 details_table = table_new(" ", "name", "description", "weight", "badness", "range", "exposure");
    1436         [ #  # ]:          0 :                 if (!details_table)
    1437                 :          0 :                         return log_oom();
    1438                 :            : 
    1439                 :          0 :                 (void) table_set_sort(details_table, 3, 1, (size_t) -1);
    1440                 :          0 :                 (void) table_set_reverse(details_table, 3, true);
    1441                 :            : 
    1442         [ #  # ]:          0 :                 if (getenv_bool("SYSTEMD_ANALYZE_DEBUG") <= 0)
    1443                 :          0 :                         (void) table_set_display(details_table, 0, 1, 2, 6, (size_t) -1);
    1444                 :            :         }
    1445                 :            : 
    1446         [ #  # ]:          0 :         for (i = 0; i < ELEMENTSOF(security_assessor_table); i++) {
    1447                 :          0 :                 const struct security_assessor *a = security_assessor_table + i;
    1448         [ #  # ]:          0 :                 _cleanup_free_ char *d = NULL;
    1449                 :            :                 uint64_t badness;
    1450                 :            :                 void *data;
    1451                 :            : 
    1452                 :          0 :                 data = (uint8_t *) info + a->offset;
    1453                 :            : 
    1454   [ #  #  #  # ]:          0 :                 if (a->default_dependencies_only && !info->default_dependencies) {
    1455                 :          0 :                         badness = UINT64_MAX;
    1456                 :          0 :                         d = strdup("Service runs in special boot phase, option does not apply");
    1457         [ #  # ]:          0 :                         if (!d)
    1458                 :          0 :                                 return log_oom();
    1459                 :            :                 } else {
    1460                 :          0 :                         r = a->assess(a, info, data, &badness, &d);
    1461         [ #  # ]:          0 :                         if (r < 0)
    1462                 :          0 :                                 return r;
    1463                 :            :                 }
    1464                 :            : 
    1465         [ #  # ]:          0 :                 assert(a->range > 0);
    1466                 :            : 
    1467         [ #  # ]:          0 :                 if (badness != UINT64_MAX) {
    1468         [ #  # ]:          0 :                         assert(badness <= a->range);
    1469                 :            : 
    1470                 :          0 :                         badness_sum += DIV_ROUND_UP(badness * a->weight, a->range);
    1471                 :          0 :                         weight_sum += a->weight;
    1472                 :            :                 }
    1473                 :            : 
    1474         [ #  # ]:          0 :                 if (details_table) {
    1475                 :          0 :                         const char *checkmark, *description, *color = NULL;
    1476                 :            :                         TableCell *cell;
    1477                 :            : 
    1478         [ #  # ]:          0 :                         if (badness == UINT64_MAX) {
    1479                 :          0 :                                 checkmark = " ";
    1480                 :          0 :                                 description = a->description_na;
    1481                 :          0 :                                 color = NULL;
    1482         [ #  # ]:          0 :                         } else if (badness == a->range) {
    1483                 :          0 :                                 checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK);
    1484                 :          0 :                                 description = a->description_bad;
    1485                 :          0 :                                 color = ansi_highlight_red();
    1486         [ #  # ]:          0 :                         } else if (badness == 0) {
    1487                 :          0 :                                 checkmark = special_glyph(SPECIAL_GLYPH_CHECK_MARK);
    1488                 :          0 :                                 description = a->description_good;
    1489                 :          0 :                                 color = ansi_highlight_green();
    1490                 :            :                         } else {
    1491                 :          0 :                                 checkmark = special_glyph(SPECIAL_GLYPH_CROSS_MARK);
    1492                 :          0 :                                 description = NULL;
    1493                 :          0 :                                 color = ansi_highlight_red();
    1494                 :            :                         }
    1495                 :            : 
    1496         [ #  # ]:          0 :                         if (d)
    1497                 :          0 :                                 description = d;
    1498                 :            : 
    1499                 :          0 :                         r = table_add_cell_full(details_table, &cell, TABLE_STRING, checkmark, 1, 1, 0, 0, 0);
    1500         [ #  # ]:          0 :                         if (r < 0)
    1501         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to add cell to table: %m");
    1502         [ #  # ]:          0 :                         if (color)
    1503                 :          0 :                                 (void) table_set_color(details_table, cell, color);
    1504                 :            : 
    1505                 :          0 :                         r = table_add_many(details_table,
    1506                 :            :                                            TABLE_STRING, a->id, TABLE_SET_URL, a->url,
    1507                 :            :                                            TABLE_STRING, description,
    1508                 :            :                                            TABLE_UINT64, a->weight, TABLE_SET_ALIGN_PERCENT, 100,
    1509                 :            :                                            TABLE_UINT64, badness, TABLE_SET_ALIGN_PERCENT, 100,
    1510                 :            :                                            TABLE_UINT64, a->range, TABLE_SET_ALIGN_PERCENT, 100,
    1511                 :            :                                            TABLE_EMPTY, TABLE_SET_ALIGN_PERCENT, 100);
    1512         [ #  # ]:          0 :                         if (r < 0)
    1513         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to add cells to table: %m");
    1514                 :            :                 }
    1515                 :            :         }
    1516                 :            : 
    1517         [ #  # ]:          0 :         assert(weight_sum > 0);
    1518                 :            : 
    1519         [ #  # ]:          0 :         if (details_table) {
    1520                 :            :                 size_t row;
    1521                 :            : 
    1522         [ #  # ]:          0 :                 for (row = 1; row < table_get_rows(details_table); row++) {
    1523                 :            :                         char buf[DECIMAL_STR_MAX(uint64_t) + 1 + DECIMAL_STR_MAX(uint64_t) + 1];
    1524                 :            :                         const uint64_t *weight, *badness, *range;
    1525                 :            :                         TableCell *cell;
    1526                 :            :                         uint64_t x;
    1527                 :            : 
    1528         [ #  # ]:          0 :                         assert_se(weight = table_get_at(details_table, row, 3));
    1529         [ #  # ]:          0 :                         assert_se(badness = table_get_at(details_table, row, 4));
    1530         [ #  # ]:          0 :                         assert_se(range = table_get_at(details_table, row, 5));
    1531                 :            : 
    1532   [ #  #  #  # ]:          0 :                         if (*badness == UINT64_MAX || *badness == 0)
    1533                 :          0 :                                 continue;
    1534                 :            : 
    1535         [ #  # ]:          0 :                         assert_se(cell = table_get_cell(details_table, row, 6));
    1536                 :            : 
    1537                 :          0 :                         x = DIV_ROUND_UP(DIV_ROUND_UP(*badness * *weight * 100U, *range), weight_sum);
    1538         [ #  # ]:          0 :                         xsprintf(buf, "%" PRIu64 ".%" PRIu64, x / 10, x % 10);
    1539                 :            : 
    1540                 :          0 :                         r = table_update(details_table, cell, TABLE_STRING, buf);
    1541         [ #  # ]:          0 :                         if (r < 0)
    1542         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to update cell in table: %m");
    1543                 :            :                 }
    1544                 :            : 
    1545                 :          0 :                 r = table_print(details_table, stdout);
    1546         [ #  # ]:          0 :                 if (r < 0)
    1547         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to output table: %m");
    1548                 :            :         }
    1549                 :            : 
    1550                 :          0 :         exposure = DIV_ROUND_UP(badness_sum * 100U, weight_sum);
    1551                 :            : 
    1552         [ #  # ]:          0 :         for (i = 0; i < ELEMENTSOF(badness_table); i++)
    1553         [ #  # ]:          0 :                 if (exposure >= badness_table[i].exposure)
    1554                 :          0 :                         break;
    1555                 :            : 
    1556         [ #  # ]:          0 :         assert(i < ELEMENTSOF(badness_table));
    1557                 :            : 
    1558         [ #  # ]:          0 :         if (details_table) {
    1559         [ #  # ]:          0 :                 _cleanup_free_ char *clickable = NULL;
    1560                 :            :                 const char *name;
    1561                 :            : 
    1562                 :            :                 /* If we shall output the details table, also print the brief summary underneath */
    1563                 :            : 
    1564         [ #  # ]:          0 :                 if (info->fragment_path) {
    1565                 :          0 :                         r = terminal_urlify_path(info->fragment_path, info->id, &clickable);
    1566         [ #  # ]:          0 :                         if (r < 0)
    1567                 :          0 :                                 return log_oom();
    1568                 :            : 
    1569                 :          0 :                         name = clickable;
    1570                 :            :                 } else
    1571                 :          0 :                         name = info->id;
    1572                 :            : 
    1573         [ #  # ]:          0 :                 printf("\n%s %sOverall exposure level for %s%s: %s%" PRIu64 ".%" PRIu64 " %s%s %s\n",
    1574                 :            :                        special_glyph(SPECIAL_GLYPH_ARROW),
    1575                 :            :                        ansi_highlight(),
    1576                 :            :                        name,
    1577                 :            :                        ansi_normal(),
    1578                 :          0 :                        colors_enabled() ? strempty(badness_table[i].color) : "",
    1579                 :            :                        exposure / 10, exposure % 10,
    1580                 :            :                        badness_table[i].name,
    1581                 :            :                        ansi_normal(),
    1582                 :            :                        special_glyph(badness_table[i].smiley));
    1583                 :            :         }
    1584                 :            : 
    1585                 :          0 :         fflush(stdout);
    1586                 :            : 
    1587         [ #  # ]:          0 :         if (overview_table) {
    1588                 :            :                 char buf[DECIMAL_STR_MAX(uint64_t) + 1 + DECIMAL_STR_MAX(uint64_t) + 1];
    1589                 :            :                 TableCell *cell;
    1590                 :            : 
    1591                 :          0 :                 r = table_add_cell(overview_table, &cell, TABLE_STRING, info->id);
    1592         [ #  # ]:          0 :                 if (r < 0)
    1593         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to add cell to table: %m");
    1594         [ #  # ]:          0 :                 if (info->fragment_path) {
    1595         [ #  # ]:          0 :                         _cleanup_free_ char *url = NULL;
    1596                 :            : 
    1597                 :          0 :                         r = file_url_from_path(info->fragment_path, &url);
    1598         [ #  # ]:          0 :                         if (r < 0)
    1599         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to generate URL from path: %m");
    1600                 :            : 
    1601                 :          0 :                         (void) table_set_url(overview_table, cell, url);
    1602                 :            :                 }
    1603                 :            : 
    1604         [ #  # ]:          0 :                 xsprintf(buf, "%" PRIu64 ".%" PRIu64, exposure / 10, exposure % 10);
    1605                 :          0 :                 r = table_add_cell(overview_table, &cell, TABLE_STRING, buf);
    1606         [ #  # ]:          0 :                 if (r < 0)
    1607         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to add cell to table: %m");
    1608                 :          0 :                 (void) table_set_align_percent(overview_table, cell, 100);
    1609                 :            : 
    1610                 :          0 :                 r = table_add_cell(overview_table, &cell, TABLE_STRING, badness_table[i].name);
    1611         [ #  # ]:          0 :                 if (r < 0)
    1612         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to add cell to table: %m");
    1613                 :          0 :                 (void) table_set_color(overview_table, cell, strempty(badness_table[i].color));
    1614                 :            : 
    1615                 :          0 :                 r = table_add_cell(overview_table, NULL, TABLE_STRING, special_glyph(badness_table[i].smiley));
    1616         [ #  # ]:          0 :                 if (r < 0)
    1617         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to add cell to table: %m");
    1618                 :            :         }
    1619                 :            : 
    1620                 :          0 :         return 0;
    1621                 :            : }
    1622                 :            : 
    1623                 :          0 : static int property_read_restrict_address_families(
    1624                 :            :                 sd_bus *bus,
    1625                 :            :                 const char *member,
    1626                 :            :                 sd_bus_message *m,
    1627                 :            :                 sd_bus_error *error,
    1628                 :            :                 void *userdata) {
    1629                 :            : 
    1630                 :          0 :         struct security_info *info = userdata;
    1631                 :            :         int whitelist, r;
    1632                 :            : 
    1633         [ #  # ]:          0 :         assert(bus);
    1634         [ #  # ]:          0 :         assert(member);
    1635         [ #  # ]:          0 :         assert(m);
    1636                 :            : 
    1637                 :          0 :         r = sd_bus_message_enter_container(m, 'r', "bas");
    1638         [ #  # ]:          0 :         if (r < 0)
    1639                 :          0 :                 return r;
    1640                 :            : 
    1641                 :          0 :         r = sd_bus_message_read(m, "b", &whitelist);
    1642         [ #  # ]:          0 :         if (r < 0)
    1643                 :          0 :                 return r;
    1644                 :            : 
    1645                 :          0 :         info->restrict_address_family_inet =
    1646                 :          0 :                 info->restrict_address_family_unix =
    1647                 :          0 :                 info->restrict_address_family_netlink =
    1648                 :          0 :                 info->restrict_address_family_packet =
    1649                 :          0 :                 info->restrict_address_family_other = whitelist;
    1650                 :            : 
    1651                 :          0 :         r = sd_bus_message_enter_container(m, 'a', "s");
    1652         [ #  # ]:          0 :         if (r < 0)
    1653                 :          0 :                 return r;
    1654                 :            : 
    1655                 :          0 :         for (;;) {
    1656                 :            :                 const char *name;
    1657                 :            : 
    1658                 :          0 :                 r = sd_bus_message_read(m, "s", &name);
    1659         [ #  # ]:          0 :                 if (r < 0)
    1660                 :          0 :                         return r;
    1661         [ #  # ]:          0 :                 if (r == 0)
    1662                 :          0 :                         break;
    1663                 :            : 
    1664         [ #  # ]:          0 :                 if (STR_IN_SET(name, "AF_INET", "AF_INET6"))
    1665                 :          0 :                         info->restrict_address_family_inet = !whitelist;
    1666         [ #  # ]:          0 :                 else if (streq(name, "AF_UNIX"))
    1667                 :          0 :                         info->restrict_address_family_unix = !whitelist;
    1668         [ #  # ]:          0 :                 else if (streq(name, "AF_NETLINK"))
    1669                 :          0 :                         info->restrict_address_family_netlink = !whitelist;
    1670         [ #  # ]:          0 :                 else if (streq(name, "AF_PACKET"))
    1671                 :          0 :                         info->restrict_address_family_packet = !whitelist;
    1672                 :            :                 else
    1673                 :          0 :                         info->restrict_address_family_other = !whitelist;
    1674                 :            :         }
    1675                 :            : 
    1676                 :          0 :         r = sd_bus_message_exit_container(m);
    1677         [ #  # ]:          0 :         if (r < 0)
    1678                 :          0 :                 return r;
    1679                 :            : 
    1680                 :          0 :         return sd_bus_message_exit_container(m);
    1681                 :            : }
    1682                 :            : 
    1683                 :          0 : static int property_read_system_call_filter(
    1684                 :            :                 sd_bus *bus,
    1685                 :            :                 const char *member,
    1686                 :            :                 sd_bus_message *m,
    1687                 :            :                 sd_bus_error *error,
    1688                 :            :                 void *userdata) {
    1689                 :            : 
    1690                 :          0 :         struct security_info *info = userdata;
    1691                 :            :         int whitelist, r;
    1692                 :            : 
    1693         [ #  # ]:          0 :         assert(bus);
    1694         [ #  # ]:          0 :         assert(member);
    1695         [ #  # ]:          0 :         assert(m);
    1696                 :            : 
    1697                 :          0 :         r = sd_bus_message_enter_container(m, 'r', "bas");
    1698         [ #  # ]:          0 :         if (r < 0)
    1699                 :          0 :                 return r;
    1700                 :            : 
    1701                 :          0 :         r = sd_bus_message_read(m, "b", &whitelist);
    1702         [ #  # ]:          0 :         if (r < 0)
    1703                 :          0 :                 return r;
    1704                 :            : 
    1705                 :          0 :         info->system_call_filter_whitelist = whitelist;
    1706                 :            : 
    1707                 :          0 :         r = sd_bus_message_enter_container(m, 'a', "s");
    1708         [ #  # ]:          0 :         if (r < 0)
    1709                 :          0 :                 return r;
    1710                 :            : 
    1711                 :          0 :         for (;;) {
    1712                 :            :                 const char *name;
    1713                 :            : 
    1714                 :          0 :                 r = sd_bus_message_read(m, "s", &name);
    1715         [ #  # ]:          0 :                 if (r < 0)
    1716                 :          0 :                         return r;
    1717         [ #  # ]:          0 :                 if (r == 0)
    1718                 :          0 :                         break;
    1719                 :            : 
    1720                 :          0 :                 r = set_ensure_allocated(&info->system_call_filter, &string_hash_ops);
    1721         [ #  # ]:          0 :                 if (r < 0)
    1722                 :          0 :                         return r;
    1723                 :            : 
    1724                 :          0 :                 r = set_put_strdup(info->system_call_filter, name);
    1725         [ #  # ]:          0 :                 if (r < 0)
    1726                 :          0 :                         return r;
    1727                 :            :         }
    1728                 :            : 
    1729                 :          0 :         r = sd_bus_message_exit_container(m);
    1730         [ #  # ]:          0 :         if (r < 0)
    1731                 :          0 :                 return r;
    1732                 :            : 
    1733                 :          0 :         return sd_bus_message_exit_container(m);
    1734                 :            : }
    1735                 :            : 
    1736                 :          0 : static int property_read_ip_address_allow(
    1737                 :            :                 sd_bus *bus,
    1738                 :            :                 const char *member,
    1739                 :            :                 sd_bus_message *m,
    1740                 :            :                 sd_bus_error *error,
    1741                 :            :                 void *userdata) {
    1742                 :            : 
    1743                 :          0 :         struct security_info *info = userdata;
    1744                 :          0 :         bool deny_ipv4 = false, deny_ipv6 = false;
    1745                 :            :         int r;
    1746                 :            : 
    1747         [ #  # ]:          0 :         assert(bus);
    1748         [ #  # ]:          0 :         assert(member);
    1749         [ #  # ]:          0 :         assert(m);
    1750                 :            : 
    1751                 :          0 :         r = sd_bus_message_enter_container(m, 'a', "(iayu)");
    1752         [ #  # ]:          0 :         if (r < 0)
    1753                 :          0 :                 return r;
    1754                 :            : 
    1755                 :          0 :         for (;;) {
    1756                 :            :                 const void *data;
    1757                 :            :                 size_t size;
    1758                 :            :                 int32_t family;
    1759                 :            :                 uint32_t prefixlen;
    1760                 :            : 
    1761                 :          0 :                 r = sd_bus_message_enter_container(m, 'r', "iayu");
    1762         [ #  # ]:          0 :                 if (r < 0)
    1763                 :          0 :                         return r;
    1764         [ #  # ]:          0 :                 if (r == 0)
    1765                 :          0 :                         break;
    1766                 :            : 
    1767                 :          0 :                 r = sd_bus_message_read(m, "i", &family);
    1768         [ #  # ]:          0 :                 if (r < 0)
    1769                 :          0 :                         return r;
    1770                 :            : 
    1771                 :          0 :                 r = sd_bus_message_read_array(m, 'y', &data, &size);
    1772         [ #  # ]:          0 :                 if (r < 0)
    1773                 :          0 :                         return r;
    1774                 :            : 
    1775                 :          0 :                 r = sd_bus_message_read(m, "u", &prefixlen);
    1776         [ #  # ]:          0 :                 if (r < 0)
    1777                 :          0 :                         return r;
    1778                 :            : 
    1779                 :          0 :                 r = sd_bus_message_exit_container(m);
    1780         [ #  # ]:          0 :                 if (r < 0)
    1781                 :          0 :                         return r;
    1782                 :            : 
    1783         [ #  # ]:          0 :                 if (streq(member, "IPAddressAllow")) {
    1784                 :            :                         union in_addr_union u;
    1785                 :            : 
    1786   [ #  #  #  #  :          0 :                         if (family == AF_INET && size == 4 && prefixlen == 8)
                   #  # ]
    1787                 :          0 :                                 memcpy(&u.in, data, size);
    1788   [ #  #  #  #  :          0 :                         else if (family == AF_INET6 && size == 16 && prefixlen == 128)
                   #  # ]
    1789                 :          0 :                                 memcpy(&u.in6, data, size);
    1790                 :            :                         else {
    1791                 :          0 :                                 info->ip_address_allow_other = true;
    1792                 :          0 :                                 continue;
    1793                 :            :                         }
    1794                 :            : 
    1795         [ #  # ]:          0 :                         if (in_addr_is_localhost(family, &u))
    1796                 :          0 :                                 info->ip_address_allow_localhost = true;
    1797                 :            :                         else
    1798                 :          0 :                                 info->ip_address_allow_other = true;
    1799                 :            :                 } else {
    1800         [ #  # ]:          0 :                         assert(streq(member, "IPAddressDeny"));
    1801                 :            : 
    1802   [ #  #  #  #  :          0 :                         if (family == AF_INET && size == 4 && prefixlen == 0)
                   #  # ]
    1803                 :          0 :                                 deny_ipv4 = true;
    1804   [ #  #  #  #  :          0 :                         else if (family == AF_INET6 && size == 16 && prefixlen == 0)
                   #  # ]
    1805                 :          0 :                                 deny_ipv6 = true;
    1806                 :            :                 }
    1807                 :            :         }
    1808                 :            : 
    1809   [ #  #  #  # ]:          0 :         info->ip_address_deny_all = deny_ipv4 && deny_ipv6;
    1810                 :            : 
    1811                 :          0 :         return sd_bus_message_exit_container(m);
    1812                 :            : }
    1813                 :            : 
    1814                 :          0 : static int property_read_ip_filters(
    1815                 :            :                 sd_bus *bus,
    1816                 :            :                 const char *member,
    1817                 :            :                 sd_bus_message *m,
    1818                 :            :                 sd_bus_error *error,
    1819                 :            :                 void *userdata) {
    1820                 :            : 
    1821                 :          0 :         struct security_info *info = userdata;
    1822                 :          0 :         _cleanup_(strv_freep) char **l = NULL;
    1823                 :            :         int r;
    1824                 :            : 
    1825         [ #  # ]:          0 :         assert(bus);
    1826         [ #  # ]:          0 :         assert(member);
    1827         [ #  # ]:          0 :         assert(m);
    1828                 :            : 
    1829                 :          0 :         r = sd_bus_message_read_strv(m, &l);
    1830         [ #  # ]:          0 :         if (r < 0)
    1831                 :          0 :                 return r;
    1832                 :            : 
    1833         [ #  # ]:          0 :         if (streq(member, "IPIngressFilterPath"))
    1834                 :          0 :                 info->ip_filters_custom_ingress = !strv_isempty(l);
    1835         [ #  # ]:          0 :         else if (streq(member, "IPEgressFilterPath"))
    1836                 :          0 :                 info->ip_filters_custom_ingress = !strv_isempty(l);
    1837                 :            : 
    1838                 :          0 :         return 0;
    1839                 :            : }
    1840                 :            : 
    1841                 :          0 : static int property_read_device_allow(
    1842                 :            :                 sd_bus *bus,
    1843                 :            :                 const char *member,
    1844                 :            :                 sd_bus_message *m,
    1845                 :            :                 sd_bus_error *error,
    1846                 :            :                 void *userdata) {
    1847                 :            : 
    1848                 :          0 :         struct security_info *info = userdata;
    1849                 :          0 :         size_t n = 0;
    1850                 :            :         int r;
    1851                 :            : 
    1852         [ #  # ]:          0 :         assert(bus);
    1853         [ #  # ]:          0 :         assert(member);
    1854         [ #  # ]:          0 :         assert(m);
    1855                 :            : 
    1856                 :          0 :         r = sd_bus_message_enter_container(m, 'a', "(ss)");
    1857         [ #  # ]:          0 :         if (r < 0)
    1858                 :          0 :                 return r;
    1859                 :            : 
    1860                 :          0 :         for (;;) {
    1861                 :            :                 const char *name, *policy;
    1862                 :            : 
    1863                 :          0 :                 r = sd_bus_message_read(m, "(ss)", &name, &policy);
    1864         [ #  # ]:          0 :                 if (r < 0)
    1865                 :          0 :                         return r;
    1866         [ #  # ]:          0 :                 if (r == 0)
    1867                 :          0 :                         break;
    1868                 :            : 
    1869                 :          0 :                 n++;
    1870                 :            :         }
    1871                 :            : 
    1872                 :          0 :         info->device_allow_non_empty = n > 0;
    1873                 :            : 
    1874                 :          0 :         return sd_bus_message_exit_container(m);
    1875                 :            : }
    1876                 :            : 
    1877                 :          0 : static int acquire_security_info(sd_bus *bus, const char *name, struct security_info *info, AnalyzeSecurityFlags flags) {
    1878                 :            : 
    1879                 :            :         static const struct bus_properties_map security_map[] = {
    1880                 :            :                 { "AmbientCapabilities",     "t",       NULL,                                    offsetof(struct security_info, ambient_capabilities)      },
    1881                 :            :                 { "CapabilityBoundingSet",   "t",       NULL,                                    offsetof(struct security_info, capability_bounding_set)   },
    1882                 :            :                 { "DefaultDependencies",     "b",       NULL,                                    offsetof(struct security_info, default_dependencies)      },
    1883                 :            :                 { "Delegate",                "b",       NULL,                                    offsetof(struct security_info, delegate)                  },
    1884                 :            :                 { "DeviceAllow",             "a(ss)",   property_read_device_allow,              0                                                         },
    1885                 :            :                 { "DevicePolicy",            "s",       NULL,                                    offsetof(struct security_info, device_policy)             },
    1886                 :            :                 { "DynamicUser",             "b",       NULL,                                    offsetof(struct security_info, dynamic_user)              },
    1887                 :            :                 { "FragmentPath",            "s",       NULL,                                    offsetof(struct security_info, fragment_path)             },
    1888                 :            :                 { "IPAddressAllow",          "a(iayu)", property_read_ip_address_allow,          0                                                         },
    1889                 :            :                 { "IPAddressDeny",           "a(iayu)", property_read_ip_address_allow,          0                                                         },
    1890                 :            :                 { "IPIngressFilterPath",     "as",      property_read_ip_filters,                0                                                         },
    1891                 :            :                 { "IPEgressFilterPath",      "as",      property_read_ip_filters,                0                                                         },
    1892                 :            :                 { "Id",                      "s",       NULL,                                    offsetof(struct security_info, id)                        },
    1893                 :            :                 { "KeyringMode",             "s",       NULL,                                    offsetof(struct security_info, keyring_mode)              },
    1894                 :            :                 { "LoadState",               "s",       NULL,                                    offsetof(struct security_info, load_state)                },
    1895                 :            :                 { "LockPersonality",         "b",       NULL,                                    offsetof(struct security_info, lock_personality)          },
    1896                 :            :                 { "MemoryDenyWriteExecute",  "b",       NULL,                                    offsetof(struct security_info, memory_deny_write_execute) },
    1897                 :            :                 { "NoNewPrivileges",         "b",       NULL,                                    offsetof(struct security_info, no_new_privileges)         },
    1898                 :            :                 { "NotifyAccess",            "s",       NULL,                                    offsetof(struct security_info, notify_access)             },
    1899                 :            :                 { "PrivateDevices",          "b",       NULL,                                    offsetof(struct security_info, private_devices)           },
    1900                 :            :                 { "PrivateMounts",           "b",       NULL,                                    offsetof(struct security_info, private_mounts)            },
    1901                 :            :                 { "PrivateNetwork",          "b",       NULL,                                    offsetof(struct security_info, private_network)           },
    1902                 :            :                 { "PrivateTmp",              "b",       NULL,                                    offsetof(struct security_info, private_tmp)               },
    1903                 :            :                 { "PrivateUsers",            "b",       NULL,                                    offsetof(struct security_info, private_users)             },
    1904                 :            :                 { "ProtectControlGroups",    "b",       NULL,                                    offsetof(struct security_info, protect_control_groups)    },
    1905                 :            :                 { "ProtectHome",             "s",       NULL,                                    offsetof(struct security_info, protect_home)              },
    1906                 :            :                 { "ProtectHostname",         "b",       NULL,                                    offsetof(struct security_info, protect_hostname)          },
    1907                 :            :                 { "ProtectKernelModules",    "b",       NULL,                                    offsetof(struct security_info, protect_kernel_modules)    },
    1908                 :            :                 { "ProtectKernelTunables",   "b",       NULL,                                    offsetof(struct security_info, protect_kernel_tunables)   },
    1909                 :            :                 { "ProtectSystem",           "s",       NULL,                                    offsetof(struct security_info, protect_system)            },
    1910                 :            :                 { "RemoveIPC",               "b",       NULL,                                    offsetof(struct security_info, remove_ipc)                },
    1911                 :            :                 { "RestrictAddressFamilies", "(bas)",   property_read_restrict_address_families, 0                                                         },
    1912                 :            :                 { "RestrictNamespaces",      "t",       NULL,                                    offsetof(struct security_info, restrict_namespaces)       },
    1913                 :            :                 { "RestrictRealtime",        "b",       NULL,                                    offsetof(struct security_info, restrict_realtime)         },
    1914                 :            :                 { "RestrictSUIDSGID",        "b",       NULL,                                    offsetof(struct security_info, restrict_suid_sgid)        },
    1915                 :            :                 { "RootDirectory",           "s",       NULL,                                    offsetof(struct security_info, root_directory)            },
    1916                 :            :                 { "RootImage",               "s",       NULL,                                    offsetof(struct security_info, root_image)                },
    1917                 :            :                 { "SupplementaryGroups",     "as",      NULL,                                    offsetof(struct security_info, supplementary_groups)      },
    1918                 :            :                 { "SystemCallArchitectures", "as",      NULL,                                    offsetof(struct security_info, system_call_architectures) },
    1919                 :            :                 { "SystemCallFilter",        "(as)",    property_read_system_call_filter,        0                                                         },
    1920                 :            :                 { "Type",                    "s",       NULL,                                    offsetof(struct security_info, type)                      },
    1921                 :            :                 { "UMask",                   "u",       NULL,                                    offsetof(struct security_info, _umask)                    },
    1922                 :            :                 { "User",                    "s",       NULL,                                    offsetof(struct security_info, user)                      },
    1923                 :            :                 {}
    1924                 :            :         };
    1925                 :            : 
    1926                 :          0 :         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    1927                 :          0 :         _cleanup_free_ char *path = NULL;
    1928                 :            :         int r;
    1929                 :            : 
    1930                 :            :         /* Note: this mangles *info on failure! */
    1931                 :            : 
    1932         [ #  # ]:          0 :         assert(bus);
    1933         [ #  # ]:          0 :         assert(name);
    1934         [ #  # ]:          0 :         assert(info);
    1935                 :            : 
    1936                 :          0 :         path = unit_dbus_path_from_name(name);
    1937         [ #  # ]:          0 :         if (!path)
    1938                 :          0 :                 return log_oom();
    1939                 :            : 
    1940                 :          0 :         r = bus_map_all_properties(
    1941                 :            :                         bus,
    1942                 :            :                         "org.freedesktop.systemd1",
    1943                 :            :                         path,
    1944                 :            :                         security_map,
    1945                 :            :                         BUS_MAP_STRDUP | BUS_MAP_BOOLEAN_AS_BOOL,
    1946                 :            :                         &error,
    1947                 :            :                         NULL,
    1948                 :            :                         info);
    1949         [ #  # ]:          0 :         if (r < 0)
    1950         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to get unit properties: %s", bus_error_message(&error, r));
    1951                 :            : 
    1952         [ #  # ]:          0 :         if (!streq_ptr(info->load_state, "loaded")) {
    1953                 :            : 
    1954         [ #  # ]:          0 :                 if (FLAGS_SET(flags, ANALYZE_SECURITY_ONLY_LOADED))
    1955                 :          0 :                         return -EMEDIUMTYPE;
    1956                 :            : 
    1957         [ #  # ]:          0 :                 if (streq_ptr(info->load_state, "not-found"))
    1958         [ #  # ]:          0 :                         log_error("Unit %s not found, cannot analyze.", name);
    1959         [ #  # ]:          0 :                 else if (streq_ptr(info->load_state, "masked"))
    1960         [ #  # ]:          0 :                         log_error("Unit %s is masked, cannot analyze.", name);
    1961                 :            :                 else
    1962         [ #  # ]:          0 :                         log_error("Unit %s not loaded properly, cannot analyze.", name);
    1963                 :            : 
    1964                 :          0 :                 return -EINVAL;
    1965                 :            :         }
    1966                 :            : 
    1967   [ #  #  #  # ]:          0 :         if (FLAGS_SET(flags, ANALYZE_SECURITY_ONLY_LONG_RUNNING) && streq_ptr(info->type, "oneshot"))
    1968                 :          0 :                 return -EMEDIUMTYPE;
    1969                 :            : 
    1970         [ #  # ]:          0 :         if (info->private_devices ||
    1971         [ #  # ]:          0 :             info->private_tmp ||
    1972         [ #  # ]:          0 :             info->protect_control_groups ||
    1973         [ #  # ]:          0 :             info->protect_kernel_tunables ||
    1974         [ #  # ]:          0 :             info->protect_kernel_modules ||
    1975         [ #  # ]:          0 :             !streq_ptr(info->protect_home, "no") ||
    1976         [ #  # ]:          0 :             !streq_ptr(info->protect_system, "no") ||
    1977         [ #  # ]:          0 :             info->root_image)
    1978                 :          0 :                 info->private_mounts = true;
    1979                 :            : 
    1980         [ #  # ]:          0 :         if (info->protect_kernel_modules)
    1981                 :          0 :                 info->capability_bounding_set &= ~(UINT64_C(1) << CAP_SYS_MODULE);
    1982                 :            : 
    1983         [ #  # ]:          0 :         if (info->private_devices)
    1984                 :          0 :                 info->capability_bounding_set &= ~((UINT64_C(1) << CAP_MKNOD) |
    1985                 :            :                                                    (UINT64_C(1) << CAP_SYS_RAWIO));
    1986                 :            : 
    1987                 :          0 :         return 0;
    1988                 :            : }
    1989                 :            : 
    1990                 :          0 : static int analyze_security_one(sd_bus *bus, const char *name, Table *overview_table, AnalyzeSecurityFlags flags) {
    1991                 :          0 :         _cleanup_(security_info_free) struct security_info info = {
    1992                 :            :                 .default_dependencies = true,
    1993                 :            :                 .capability_bounding_set = UINT64_MAX,
    1994                 :            :                 .restrict_namespaces = UINT64_MAX,
    1995                 :            :                 ._umask = 0002,
    1996                 :            :         };
    1997                 :            :         int r;
    1998                 :            : 
    1999         [ #  # ]:          0 :         assert(bus);
    2000         [ #  # ]:          0 :         assert(name);
    2001                 :            : 
    2002                 :          0 :         r = acquire_security_info(bus, name, &info, flags);
    2003         [ #  # ]:          0 :         if (r == -EMEDIUMTYPE) /* Ignore this one because not loaded or Type is oneshot */
    2004                 :          0 :                 return 0;
    2005         [ #  # ]:          0 :         if (r < 0)
    2006                 :          0 :                 return r;
    2007                 :            : 
    2008                 :          0 :         r = assess(&info, overview_table, flags);
    2009         [ #  # ]:          0 :         if (r < 0)
    2010                 :          0 :                 return r;
    2011                 :            : 
    2012                 :          0 :         return 0;
    2013                 :            : }
    2014                 :            : 
    2015                 :          0 : int analyze_security(sd_bus *bus, char **units, AnalyzeSecurityFlags flags) {
    2016                 :          0 :         _cleanup_(table_unrefp) Table *overview_table = NULL;
    2017                 :          0 :         int ret = 0, r;
    2018                 :            : 
    2019         [ #  # ]:          0 :         assert(bus);
    2020                 :            : 
    2021         [ #  # ]:          0 :         if (strv_length(units) != 1) {
    2022                 :          0 :                 overview_table = table_new("unit", "exposure", "predicate", "happy");
    2023         [ #  # ]:          0 :                 if (!overview_table)
    2024                 :          0 :                         return log_oom();
    2025                 :            :         }
    2026                 :            : 
    2027         [ #  # ]:          0 :         if (strv_isempty(units)) {
    2028         [ #  # ]:          0 :                 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
    2029         [ #  # ]:          0 :                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
    2030         [ #  # ]:          0 :                 _cleanup_strv_free_ char **list = NULL;
    2031                 :          0 :                 size_t allocated = 0, n = 0;
    2032                 :            :                 char **i;
    2033                 :            : 
    2034                 :          0 :                 r = sd_bus_call_method(
    2035                 :            :                                 bus,
    2036                 :            :                                 "org.freedesktop.systemd1",
    2037                 :            :                                 "/org/freedesktop/systemd1",
    2038                 :            :                                 "org.freedesktop.systemd1.Manager",
    2039                 :            :                                 "ListUnits",
    2040                 :            :                                 &error,
    2041                 :            :                                 &reply,
    2042                 :            :                                 NULL);
    2043         [ #  # ]:          0 :                 if (r < 0)
    2044         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to list units: %s", bus_error_message(&error, r));
    2045                 :            : 
    2046                 :          0 :                 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "(ssssssouso)");
    2047         [ #  # ]:          0 :                 if (r < 0)
    2048         [ #  # ]:          0 :                         return bus_log_parse_error(r);
    2049                 :            : 
    2050                 :          0 :                 for (;;) {
    2051                 :            :                         UnitInfo info;
    2052                 :          0 :                         char *copy = NULL;
    2053                 :            : 
    2054                 :          0 :                         r = bus_parse_unit_info(reply, &info);
    2055         [ #  # ]:          0 :                         if (r < 0)
    2056         [ #  # ]:          0 :                                 return bus_log_parse_error(r);
    2057         [ #  # ]:          0 :                         if (r == 0)
    2058                 :          0 :                                 break;
    2059                 :            : 
    2060         [ #  # ]:          0 :                         if (!endswith(info.id, ".service"))
    2061                 :          0 :                                 continue;
    2062                 :            : 
    2063         [ #  # ]:          0 :                         if (!GREEDY_REALLOC(list, allocated, n + 2))
    2064                 :          0 :                                 return log_oom();
    2065                 :            : 
    2066                 :          0 :                         copy = strdup(info.id);
    2067         [ #  # ]:          0 :                         if (!copy)
    2068                 :          0 :                                 return log_oom();
    2069                 :            : 
    2070                 :          0 :                         list[n++] = copy;
    2071                 :          0 :                         list[n] = NULL;
    2072                 :            :                 }
    2073                 :            : 
    2074                 :          0 :                 strv_sort(list);
    2075                 :            : 
    2076                 :          0 :                 flags |= ANALYZE_SECURITY_SHORT|ANALYZE_SECURITY_ONLY_LOADED|ANALYZE_SECURITY_ONLY_LONG_RUNNING;
    2077                 :            : 
    2078   [ #  #  #  # ]:          0 :                 STRV_FOREACH(i, list) {
    2079                 :          0 :                         r = analyze_security_one(bus, *i, overview_table, flags);
    2080   [ #  #  #  # ]:          0 :                         if (r < 0 && ret >= 0)
    2081                 :          0 :                                 ret = r;
    2082                 :            :                 }
    2083                 :            : 
    2084                 :            :         } else {
    2085                 :            :                 char **i;
    2086                 :            : 
    2087   [ #  #  #  # ]:          0 :                 STRV_FOREACH(i, units) {
    2088   [ #  #  #  # ]:          0 :                         _cleanup_free_ char *mangled = NULL, *instance = NULL;
    2089                 :            :                         const char *name;
    2090                 :            : 
    2091   [ #  #  #  #  :          0 :                         if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT) && i != units) {
                   #  # ]
    2092                 :          0 :                                 putc('\n', stdout);
    2093                 :          0 :                                 fflush(stdout);
    2094                 :            :                         }
    2095                 :            : 
    2096                 :          0 :                         r = unit_name_mangle_with_suffix(*i, 0, ".service", &mangled);
    2097         [ #  # ]:          0 :                         if (r < 0)
    2098         [ #  # ]:          0 :                                 return log_error_errno(r, "Failed to mangle unit name '%s': %m", *i);
    2099                 :            : 
    2100         [ #  # ]:          0 :                         if (!endswith(mangled, ".service")) {
    2101         [ #  # ]:          0 :                                 log_error("Unit %s is not a service unit, refusing.", *i);
    2102                 :          0 :                                 return -EINVAL;
    2103                 :            :                         }
    2104                 :            : 
    2105         [ #  # ]:          0 :                         if (unit_name_is_valid(mangled, UNIT_NAME_TEMPLATE)) {
    2106                 :          0 :                                 r = unit_name_replace_instance(mangled, "test-instance", &instance);
    2107         [ #  # ]:          0 :                                 if (r < 0)
    2108                 :          0 :                                         return log_oom();
    2109                 :            : 
    2110                 :          0 :                                 name = instance;
    2111                 :            :                         } else
    2112                 :          0 :                                 name = mangled;
    2113                 :            : 
    2114                 :          0 :                         r = analyze_security_one(bus, name, overview_table, flags);
    2115   [ #  #  #  # ]:          0 :                         if (r < 0 && ret >= 0)
    2116                 :          0 :                                 ret = r;
    2117                 :            :                 }
    2118                 :            :         }
    2119                 :            : 
    2120         [ #  # ]:          0 :         if (overview_table) {
    2121   [ #  #  #  # ]:          0 :                 if (!FLAGS_SET(flags, ANALYZE_SECURITY_SHORT)) {
    2122                 :          0 :                         putc('\n', stdout);
    2123                 :          0 :                         fflush(stdout);
    2124                 :            :                 }
    2125                 :            : 
    2126                 :          0 :                 r = table_print(overview_table, stdout);
    2127         [ #  # ]:          0 :                 if (r < 0)
    2128         [ #  # ]:          0 :                         return log_error_errno(r, "Failed to output table: %m");
    2129                 :            :         }
    2130                 :            : 
    2131                 :          0 :         return ret;
    2132                 :            : }

Generated by: LCOV version 1.14