chiark / gitweb /
sd-bus: use SO_PEERGROUPS when available to identify groups of peer
authorLennart Poettering <lennart@poettering.net>
Sat, 30 Dec 2017 14:19:15 +0000 (15:19 +0100)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:49:53 +0000 (07:49 +0200)
src/libelogind/sd-bus/bus-control.c
src/libelogind/sd-bus/bus-internal.h
src/libelogind/sd-bus/bus-socket.c
src/libelogind/sd-bus/sd-bus.c

index ffe0af2ce77fa757c6bd1d54fcbaed1b3e2e88b5..0b39115d16a14b9042e72697b7a4d75d234d1fbb 100644 (file)
@@ -555,15 +555,16 @@ _public_ int sd_bus_get_name_creds(
 static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
         pid_t pid = 0;
-        bool do_label;
+        bool do_label, do_groups;
         int r;
 
         assert(bus);
 
         do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
+        do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
 
         /* Avoid allocating anything if we have no chance of returning useful data */
-        if (!bus->ucred_valid && !do_label)
+        if (!bus->ucred_valid && !do_label && !do_groups)
                 return -ENODATA;
 
         c = bus_creds_new();
@@ -595,6 +596,16 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **
                 c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
         }
 
+        if (do_groups) {
+                c->supplementary_gids = newdup(gid_t, bus->groups, bus->n_groups);
+                if (!c->supplementary_gids)
+                        return -ENOMEM;
+
+                c->n_supplementary_gids = bus->n_groups;
+
+                c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
+        }
+
         r = bus_creds_add_more(c, mask, pid, 0);
         if (r < 0)
                 return r;
index 96474e9a3d50184cc73d7eac084c84d546ca1e37..8557d67e119d2002b43a900e8d3f14f1314000f0 100644 (file)
@@ -261,6 +261,8 @@ struct sd_bus {
 
         struct ucred ucred;
         char *label;
+        gid_t *groups;
+        size_t n_groups;
 
         uint64_t creds_mask;
 
index 013bdb05a002adc983eda5fdc8fe3cd8d891a652..0a1d36a9d3d729d5cc0b34a100b442d7143ddeae 100644 (file)
@@ -603,14 +603,27 @@ static void bus_get_peercred(sd_bus *b) {
         int r;
 
         assert(b);
+        assert(!b->ucred_valid);
+        assert(!b->label);
+        assert(b->n_groups == (size_t) -1);
 
         /* Get the peer for socketpair() sockets */
         b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
 
         /* Get the SELinux context of the peer */
         r = getpeersec(b->input_fd, &b->label);
-        if (r < 0 && r != -EOPNOTSUPP)
+        if (r < 0 && !IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
                 log_debug_errno(r, "Failed to determine peer security context: %m");
+
+        /* Get the list of auxiliary groups of the peer */
+        r = getpeergroups(b->input_fd, &b->groups);
+        if (r < 0) {
+                if (!IN_SET(r, -EOPNOTSUPP, -ENOPROTOOPT))
+                        log_debug_errno(r, "Failed to determine peer groups list: %m");
+
+                b->n_groups = (size_t) -1;
+        } else
+                b->n_groups = (size_t) r;
 }
 
 static int bus_socket_start_auth_client(sd_bus *b) {
index 2b372e4363282dbfdf3bd8ad472a90dd24bab78b..27e52586fa5d14b396c2c693b5758703bc9a29e1 100644 (file)
@@ -139,6 +139,7 @@ static void bus_free(sd_bus *b) {
         bus_close_fds(b);
 
         free(b->label);
+        free(b->groups);
         free(b->rbuffer);
         free(b->unique_name);
         free(b->auth_buffer);
@@ -190,6 +191,7 @@ _public_ int sd_bus_new(sd_bus **ret) {
         r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
         r->attach_flags |= KDBUS_ATTACH_NAMES;
         r->original_pid = getpid_cached();
+        r->n_groups = (size_t) -1;
 
         assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);