]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
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)
committerLennart Poettering <lennart@poettering.net>
Thu, 4 Jan 2018 12:28:24 +0000 (13:28 +0100)
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/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 378c408ea3942d341873dc8a011a7647d9a370af..4175ca3efe0edea950cceaa2481673c150a24a3e 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 5fb15a7aaff33825c552cdcb59c43e7930b8ca60..847553b6a85e3a1e130748d11bc027ceb3e483a6 100644 (file)
@@ -134,6 +134,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);
@@ -185,6 +186,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);