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

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <string.h>
       5                 :            : 
       6                 :            : #include "sd-device.h"
       7                 :            : 
       8                 :            : #include "acl-util.h"
       9                 :            : #include "alloc-util.h"
      10                 :            : #include "device-util.h"
      11                 :            : #include "dirent-util.h"
      12                 :            : #include "escape.h"
      13                 :            : #include "fd-util.h"
      14                 :            : #include "format-util.h"
      15                 :            : #include "logind-acl.h"
      16                 :            : #include "set.h"
      17                 :            : #include "string-util.h"
      18                 :            : #include "util.h"
      19                 :            : 
      20                 :          0 : static int flush_acl(acl_t acl) {
      21                 :            :         acl_entry_t i;
      22                 :            :         int found;
      23                 :          0 :         bool changed = false;
      24                 :            : 
      25         [ #  # ]:          0 :         assert(acl);
      26                 :            : 
      27         [ #  # ]:          0 :         for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
      28                 :            :              found > 0;
      29                 :          0 :              found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
      30                 :            : 
      31                 :            :                 acl_tag_t tag;
      32                 :            : 
      33         [ #  # ]:          0 :                 if (acl_get_tag_type(i, &tag) < 0)
      34                 :          0 :                         return -errno;
      35                 :            : 
      36         [ #  # ]:          0 :                 if (tag != ACL_USER)
      37                 :          0 :                         continue;
      38                 :            : 
      39         [ #  # ]:          0 :                 if (acl_delete_entry(acl, i) < 0)
      40                 :          0 :                         return -errno;
      41                 :            : 
      42                 :          0 :                 changed = true;
      43                 :            :         }
      44                 :            : 
      45         [ #  # ]:          0 :         if (found < 0)
      46                 :          0 :                 return -errno;
      47                 :            : 
      48                 :          0 :         return changed;
      49                 :            : }
      50                 :            : 
      51                 :          0 : int devnode_acl(const char *path,
      52                 :            :                 bool flush,
      53                 :            :                 bool del, uid_t old_uid,
      54                 :            :                 bool add, uid_t new_uid) {
      55                 :            : 
      56                 :            :         acl_t acl;
      57                 :          0 :         int r = 0;
      58                 :          0 :         bool changed = false;
      59                 :            : 
      60         [ #  # ]:          0 :         assert(path);
      61                 :            : 
      62                 :          0 :         acl = acl_get_file(path, ACL_TYPE_ACCESS);
      63         [ #  # ]:          0 :         if (!acl)
      64                 :          0 :                 return -errno;
      65                 :            : 
      66         [ #  # ]:          0 :         if (flush) {
      67                 :            : 
      68                 :          0 :                 r = flush_acl(acl);
      69         [ #  # ]:          0 :                 if (r < 0)
      70                 :          0 :                         goto finish;
      71         [ #  # ]:          0 :                 if (r > 0)
      72                 :          0 :                         changed = true;
      73                 :            : 
      74   [ #  #  #  # ]:          0 :         } else if (del && old_uid > 0) {
      75                 :            :                 acl_entry_t entry;
      76                 :            : 
      77                 :          0 :                 r = acl_find_uid(acl, old_uid, &entry);
      78         [ #  # ]:          0 :                 if (r < 0)
      79                 :          0 :                         goto finish;
      80                 :            : 
      81         [ #  # ]:          0 :                 if (r > 0) {
      82         [ #  # ]:          0 :                         if (acl_delete_entry(acl, entry) < 0) {
      83                 :          0 :                                 r = -errno;
      84                 :          0 :                                 goto finish;
      85                 :            :                         }
      86                 :            : 
      87                 :          0 :                         changed = true;
      88                 :            :                 }
      89                 :            :         }
      90                 :            : 
      91   [ #  #  #  # ]:          0 :         if (add && new_uid > 0) {
      92                 :            :                 acl_entry_t entry;
      93                 :            :                 acl_permset_t permset;
      94                 :            :                 int rd, wt;
      95                 :            : 
      96                 :          0 :                 r = acl_find_uid(acl, new_uid, &entry);
      97         [ #  # ]:          0 :                 if (r < 0)
      98                 :          0 :                         goto finish;
      99                 :            : 
     100         [ #  # ]:          0 :                 if (r == 0) {
     101         [ #  # ]:          0 :                         if (acl_create_entry(&acl, &entry) < 0) {
     102                 :          0 :                                 r = -errno;
     103                 :          0 :                                 goto finish;
     104                 :            :                         }
     105                 :            : 
     106   [ #  #  #  # ]:          0 :                         if (acl_set_tag_type(entry, ACL_USER) < 0 ||
     107                 :          0 :                             acl_set_qualifier(entry, &new_uid) < 0) {
     108                 :          0 :                                 r = -errno;
     109                 :          0 :                                 goto finish;
     110                 :            :                         }
     111                 :            :                 }
     112                 :            : 
     113         [ #  # ]:          0 :                 if (acl_get_permset(entry, &permset) < 0) {
     114                 :          0 :                         r = -errno;
     115                 :          0 :                         goto finish;
     116                 :            :                 }
     117                 :            : 
     118                 :          0 :                 rd = acl_get_perm(permset, ACL_READ);
     119         [ #  # ]:          0 :                 if (rd < 0) {
     120                 :          0 :                         r = -errno;
     121                 :          0 :                         goto finish;
     122                 :            :                 }
     123                 :            : 
     124                 :          0 :                 wt = acl_get_perm(permset, ACL_WRITE);
     125         [ #  # ]:          0 :                 if (wt < 0) {
     126                 :          0 :                         r = -errno;
     127                 :          0 :                         goto finish;
     128                 :            :                 }
     129                 :            : 
     130   [ #  #  #  # ]:          0 :                 if (!rd || !wt) {
     131                 :            : 
     132         [ #  # ]:          0 :                         if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) {
     133                 :          0 :                                 r = -errno;
     134                 :          0 :                                 goto finish;
     135                 :            :                         }
     136                 :            : 
     137                 :          0 :                         changed = true;
     138                 :            :                 }
     139                 :            :         }
     140                 :            : 
     141         [ #  # ]:          0 :         if (!changed)
     142                 :          0 :                 goto finish;
     143                 :            : 
     144         [ #  # ]:          0 :         if (acl_calc_mask(&acl) < 0) {
     145                 :          0 :                 r = -errno;
     146                 :          0 :                 goto finish;
     147                 :            :         }
     148                 :            : 
     149         [ #  # ]:          0 :         if (acl_set_file(path, ACL_TYPE_ACCESS, acl) < 0) {
     150                 :          0 :                 r = -errno;
     151                 :          0 :                 goto finish;
     152                 :            :         }
     153                 :            : 
     154                 :          0 :         r = 0;
     155                 :            : 
     156                 :          0 : finish:
     157                 :          0 :         acl_free(acl);
     158                 :            : 
     159                 :          0 :         return r;
     160                 :            : }
     161                 :            : 
     162                 :          0 : int devnode_acl_all(const char *seat,
     163                 :            :                     bool flush,
     164                 :            :                     bool del, uid_t old_uid,
     165                 :            :                     bool add, uid_t new_uid) {
     166                 :            : 
     167                 :          0 :         _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
     168                 :          0 :         _cleanup_set_free_free_ Set *nodes = NULL;
     169                 :          0 :         _cleanup_closedir_ DIR *dir = NULL;
     170                 :            :         struct dirent *dent;
     171                 :            :         sd_device *d;
     172                 :            :         Iterator i;
     173                 :            :         char *n;
     174                 :            :         int r;
     175                 :            : 
     176                 :          0 :         nodes = set_new(&path_hash_ops);
     177         [ #  # ]:          0 :         if (!nodes)
     178                 :          0 :                 return -ENOMEM;
     179                 :            : 
     180                 :          0 :         r = sd_device_enumerator_new(&e);
     181         [ #  # ]:          0 :         if (r < 0)
     182                 :          0 :                 return r;
     183                 :            : 
     184         [ #  # ]:          0 :         if (isempty(seat))
     185                 :          0 :                 seat = "seat0";
     186                 :            : 
     187                 :            :         /* We can only match by one tag in libudev. We choose
     188                 :            :          * "uaccess" for that. If we could match for two tags here we
     189                 :            :          * could add the seat name as second match tag, but this would
     190                 :            :          * be hardly optimizable in libudev, and hence checking the
     191                 :            :          * second tag manually in our loop is a good solution. */
     192                 :          0 :         r = sd_device_enumerator_add_match_tag(e, "uaccess");
     193         [ #  # ]:          0 :         if (r < 0)
     194                 :          0 :                 return r;
     195                 :            : 
     196         [ #  # ]:          0 :         FOREACH_DEVICE(e, d) {
     197                 :            :                 const char *node, *sn;
     198                 :            : 
     199   [ #  #  #  # ]:          0 :                 if (sd_device_get_property_value(d, "ID_SEAT", &sn) < 0 || isempty(sn))
     200                 :          0 :                         sn = "seat0";
     201                 :            : 
     202         [ #  # ]:          0 :                 if (!streq(seat, sn))
     203                 :          0 :                         continue;
     204                 :            : 
     205                 :            :                 /* In case people mistag devices with nodes, we need to ignore this */
     206         [ #  # ]:          0 :                 if (sd_device_get_devname(d, &node) < 0)
     207                 :          0 :                         continue;
     208                 :            : 
     209   [ #  #  #  #  :          0 :                 log_device_debug(d, "Found udev node %s for seat %s", node, seat);
                   #  # ]
     210                 :          0 :                 r = set_put_strdup(nodes, node);
     211         [ #  # ]:          0 :                 if (r < 0)
     212                 :          0 :                         return r;
     213                 :            :         }
     214                 :            : 
     215                 :            :         /* udev exports "dead" device nodes to allow module on-demand loading,
     216                 :            :          * these devices are not known to the kernel at this moment */
     217                 :          0 :         dir = opendir("/run/udev/static_node-tags/uaccess");
     218         [ #  # ]:          0 :         if (dir) {
     219   [ #  #  #  #  :          0 :                 FOREACH_DIRENT(dent, dir, return -errno) {
                   #  # ]
     220      [ #  #  # ]:          0 :                         _cleanup_free_ char *unescaped_devname = NULL;
     221                 :            : 
     222         [ #  # ]:          0 :                         if (cunescape(dent->d_name, UNESCAPE_RELAX, &unescaped_devname) < 0)
     223                 :          0 :                                 return -ENOMEM;
     224                 :            : 
     225                 :          0 :                         n = path_join("/dev", unescaped_devname);
     226         [ #  # ]:          0 :                         if (!n)
     227                 :          0 :                                 return -ENOMEM;
     228                 :            : 
     229         [ #  # ]:          0 :                         log_debug("Found static node %s for seat %s", n, seat);
     230                 :          0 :                         r = set_consume(nodes, n);
     231         [ #  # ]:          0 :                         if (r == -EEXIST)
     232                 :          0 :                                 continue;
     233         [ #  # ]:          0 :                         if (r < 0)
     234                 :          0 :                                 return r;
     235                 :            :                 }
     236                 :            :         }
     237                 :            : 
     238                 :          0 :         r = 0;
     239         [ #  # ]:          0 :         SET_FOREACH(n, nodes, i) {
     240                 :            :                 int k;
     241                 :            : 
     242   [ #  #  #  #  :          0 :                 log_debug("Changing ACLs at %s for seat %s (uid "UID_FMT"→"UID_FMT"%s%s)",
                   #  # ]
     243                 :            :                           n, seat, old_uid, new_uid,
     244                 :            :                           del ? " del" : "", add ? " add" : "");
     245                 :            : 
     246                 :          0 :                 k = devnode_acl(n, flush, del, old_uid, add, new_uid);
     247         [ #  # ]:          0 :                 if (k == -ENOENT)
     248         [ #  # ]:          0 :                         log_debug("Device %s disappeared while setting ACLs", n);
     249   [ #  #  #  # ]:          0 :                 else if (k < 0 && r == 0)
     250                 :          0 :                         r = k;
     251                 :            :         }
     252                 :            : 
     253                 :          0 :         return r;
     254                 :            : }

Generated by: LCOV version 1.14