LCOV - code coverage report
Current view: top level - login - logind-acl.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 127 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 3 0.0 %

          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