From 18ac4643cb8f664a02c609f945179ab0951a92ae Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 30 Dec 2017 15:19:15 +0100 Subject: [PATCH] sd-bus: use SO_PEERGROUPS when available to identify groups of peer --- src/libsystemd/sd-bus/bus-control.c | 15 +++++++++++++-- src/libsystemd/sd-bus/bus-internal.h | 2 ++ src/libsystemd/sd-bus/bus-socket.c | 15 ++++++++++++++- src/libsystemd/sd-bus/sd-bus.c | 2 ++ 4 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c index ffe0af2ce77..0b39115d16a 100644 --- a/src/libsystemd/sd-bus/bus-control.c +++ b/src/libsystemd/sd-bus/bus-control.c @@ -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; diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h index 378c408ea39..4175ca3efe0 100644 --- a/src/libsystemd/sd-bus/bus-internal.h +++ b/src/libsystemd/sd-bus/bus-internal.h @@ -261,6 +261,8 @@ struct sd_bus { struct ucred ucred; char *label; + gid_t *groups; + size_t n_groups; uint64_t creds_mask; diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 013bdb05a00..0a1d36a9d3d 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -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) { diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index 5fb15a7aaff..847553b6a85 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -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); -- 2.39.2