mirror of
https://github.com/morgan9e/systemd
synced 2026-04-15 17:06:39 +09:00
sd-bus: also read supplementary gids from bus driver
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user