sd-bus: also read supplementary gids from bus driver

This commit is contained in:
Lennart Poettering
2024-01-26 17:09:02 +01:00
parent 71be64064c
commit 25fd5343ca
2 changed files with 87 additions and 4 deletions

View File

@@ -483,8 +483,8 @@ _public_ int sd_bus_get_name_creds(
}
if (mask != 0) {
bool need_pid, need_uid, need_gids, need_selinux, need_separate_calls, need_pidfd, need_augment;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
bool need_pid, need_uid, need_selinux, need_separate_calls, need_pidfd, need_augment;
_cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
c = bus_creds_new();
@@ -513,10 +513,11 @@ _public_ int sd_bus_get_name_creds(
need_pid = (mask & SD_BUS_CREDS_PID) || need_augment;
need_uid = mask & SD_BUS_CREDS_EUID;
need_gids = mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
need_selinux = mask & SD_BUS_CREDS_SELINUX_CONTEXT;
need_pidfd = (mask & SD_BUS_CREDS_PIDFD) || need_augment;
if (need_pid + need_uid + need_selinux + need_pidfd > 1) {
if (need_pid + need_uid + need_selinux + need_pidfd + need_gids > 1) {
/* If we need more than one of the credentials, then use GetConnectionCredentials() */
@@ -626,6 +627,49 @@ _public_ int sd_bus_get_name_creds(
close_and_replace(c->pidfd, fd);
c->mask |= SD_BUS_CREDS_PIDFD;
}
} else if (need_gids && streq(m, "UnixGroupIDs")) {
/* Note that D-Bus actualy only gives us a combined list of
* primary gid and supplementary gids. And we don't know
* which one the primary one is. We'll take the whole shebang
* hence and use it as the supplementary group list, and not
* initialize the primary gid field. This is slightly
* incorrect of course, but only slightly, as in effect if
* the primary gid is also listed in the supplementary gid
* it has zero effect. */
r = sd_bus_message_enter_container(reply, 'v', "au");
if (r < 0)
return r;
r = sd_bus_message_enter_container(reply, 'a', "u");
if (r < 0)
return r;
for (;;) {
uint32_t u;
r = sd_bus_message_read(reply, "u", &u);
if (r < 0)
return r;
if (r == 0)
break;
if (!GREEDY_REALLOC(c->supplementary_gids, c->n_supplementary_gids+1))
return -ENOMEM;
c->supplementary_gids[c->n_supplementary_gids++] = (gid_t) u;
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
} else {
r = sd_bus_message_skip(reply, "v");
if (r < 0)

View File

@@ -10,7 +10,34 @@
#include "fd-util.h"
#include "process-util.h"
#include "socket-util.h"
#include "sort-util.h"
#include "tests.h"
#include "user-util.h"
static bool gid_list_contained(const gid_t *a, size_t n, const gid_t *b, size_t m) {
assert_se(a || n == 0);
assert_se(b || m == 0);
/* Checks if every entry in a[] is also in b[] */
for (size_t i = 0; i < n; i++) {
size_t j;
for (j = 0; j < m; j++)
if (a[i] == b[j])
break;
if (j >= m)
return false;
}
return true;
}
static bool gid_list_same(const gid_t *a, size_t n, const gid_t *b, size_t m) {
return gid_list_contained(a, n, b, m) &&
gid_list_contained(b, m, a, n);
}
static void *server(void *p) {
_cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
@@ -29,11 +56,11 @@ static void *server(void *p) {
assert_se(sd_bus_set_fd(bus, fd, fd) >= 0);
TAKE_FD(fd);
assert_se(sd_bus_set_server(bus, true, id) >= 0);
assert_se(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD) >= 0);
assert_se(sd_bus_negotiate_creds(bus, 1, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS) >= 0);
assert_se(sd_bus_start(bus) >= 0);
assert_se(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD, &c) >= 0);
assert_se(sd_bus_get_owner_creds(bus, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_DESCRIPTION|SD_BUS_CREDS_PIDFD|SD_BUS_CREDS_SUPPLEMENTARY_GIDS, &c) >= 0);
bus_creds_dump(c, /* f= */ NULL, /* terse= */ false);
@@ -57,6 +84,18 @@ static void *server(void *p) {
assert_se(pidref.pid == getpid_cached());
}
const gid_t *gl = NULL;
int n;
n = sd_bus_creds_get_supplementary_gids(c, &gl);
if (n >= 0) {
_cleanup_free_ gid_t *gg = NULL;
r = getgroups_alloc(&gg);
assert_se(r >= 0);
assert_se(gid_list_same(gl, n, gg, r));
}
const char *comm;
assert_se(sd_bus_creds_get_comm(c, &comm) >= 0);
assert_se(pid_get_comm(0, &our_comm) >= 0);