summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-11-24 21:41:40 +0100
committerLennart Poettering <lennart@poettering.net>2014-11-25 14:28:34 +0100
commit705a415f684f8e9ee19983e5859de00bbb1477cb (patch)
tree5cbabb53de92d7ee21ada427c24a88d18073c9dc
parent1d58a1fe13cd725110be595c40cdc973d7e57d9e (diff)
sd-bus: update to current kernel version, by splitting off the extended KDBUS_ITEM_PIDS structure from KDBUS_ITEM_CREDS
Also: - adds support for euid, suid, fsuid, egid, sgid, fsgid fields. - makes augmentation of creds with data from /proc explicitly controllable to give apps better control over this, given that this is racy. - enables augmentation for kdbus connections (previously we only did it for dbus1). This is useful since with recent kdbus versions it is possible for clients to control the metadata they want to send. - changes sd_bus_query_sender_privilege() to take the euid of the client into consideration, if known - when we don't have permissions to read augmentation data from /proc, don't fail, just don't add the data in
-rw-r--r--src/bus-proxyd/bus-proxyd.c10
-rw-r--r--src/libsystemd/sd-bus/bus-control.c122
-rw-r--r--src/libsystemd/sd-bus/bus-convenience.c25
-rw-r--r--src/libsystemd/sd-bus/bus-creds.c369
-rw-r--r--src/libsystemd/sd-bus/bus-creds.h7
-rw-r--r--src/libsystemd/sd-bus/bus-dump.c21
-rw-r--r--src/libsystemd/sd-bus/bus-internal.h2
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c98
-rw-r--r--src/libsystemd/sd-bus/kdbus.h103
-rw-r--r--src/libsystemd/sd-bus/sd-bus.c2
-rw-r--r--src/systemd/sd-bus.h57
11 files changed, 596 insertions, 220 deletions
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c
index 9c4f2a6ad9..32c8242221 100644
--- a/src/bus-proxyd/bus-proxyd.c
+++ b/src/bus-proxyd/bus-proxyd.c
@@ -1242,9 +1242,17 @@ int main(int argc, char *argv[]) {
}
if (ucred.pid > 0) {
- a->fake_creds.pid = ucred.pid;
+ a->fake_pids.pid = ucred.pid;
+ a->fake_pids_valid = true;
+
a->fake_creds.uid = ucred.uid;
+ a->fake_creds.euid = (uid_t) -1;
+ a->fake_creds.suid = (uid_t) -1;
+ a->fake_creds.fsuid = (uid_t) -1;
a->fake_creds.gid = ucred.gid;
+ a->fake_creds.egid = (gid_t) -1;
+ a->fake_creds.sgid = (gid_t) -1;
+ a->fake_creds.fsgid = (gid_t) -1;
a->fake_creds_valid = true;
}
diff --git a/src/libsystemd/sd-bus/bus-control.c b/src/libsystemd/sd-bus/bus-control.c
index c25a4911f5..7db912b64b 100644
--- a/src/libsystemd/sd-bus/bus-control.c
+++ b/src/libsystemd/sd-bus/bus-control.c
@@ -405,24 +405,65 @@ static int bus_populate_creds_from_items(sd_bus *bus,
switch (item->type) {
+ case KDBUS_ITEM_PIDS:
+
+ if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
+ c->pid = (pid_t) item->pids.pid;
+ c->mask |= SD_BUS_CREDS_PID;
+ }
+
+ if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
+ c->tid = (pid_t) item->pids.tid;
+ c->mask |= SD_BUS_CREDS_TID;
+ }
+
+ if (mask & SD_BUS_CREDS_PID_STARTTIME && item->pids.starttime > 0) {
+ c->pid_starttime = item->pids.starttime;
+ c->mask |= SD_BUS_CREDS_PID_STARTTIME;
+ }
+
+ break;
+
case KDBUS_ITEM_CREDS:
- m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & mask;
- if (m) {
+ if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != (uid_t) -1) {
c->uid = (uid_t) item->creds.uid;
- c->pid = (pid_t) item->creds.pid;
+ c->mask |= SD_BUS_CREDS_UID;
+ }
+
+ if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != (uid_t) -1) {
+ c->euid = (uid_t) item->creds.euid;
+ c->mask |= SD_BUS_CREDS_EUID;
+ }
+
+ if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != (uid_t) -1) {
+ c->suid = (uid_t) item->creds.suid;
+ c->mask |= SD_BUS_CREDS_SUID;
+ }
+
+ if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != (uid_t) -1) {
+ c->fsuid = (uid_t) item->creds.fsuid;
+ c->mask |= SD_BUS_CREDS_FSUID;
+ }
+
+ if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != (gid_t) -1) {
c->gid = (gid_t) item->creds.gid;
- c->mask |= m;
+ c->mask |= SD_BUS_CREDS_GID;
}
- if (mask & SD_BUS_CREDS_TID && item->creds.tid > 0) {
- c->tid = (pid_t) item->creds.tid;
- c->mask |= SD_BUS_CREDS_TID;
+ if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != (gid_t) -1) {
+ c->egid = (gid_t) item->creds.egid;
+ c->mask |= SD_BUS_CREDS_EGID;
}
- if (mask & SD_BUS_CREDS_PID_STARTTIME && item->creds.starttime > 0) {
- c->pid_starttime = item->creds.starttime;
- c->mask |= SD_BUS_CREDS_PID_STARTTIME;
+ if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != (gid_t) -1) {
+ c->sgid = (gid_t) item->creds.sgid;
+ c->mask |= SD_BUS_CREDS_SGID;
+ }
+
+ if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != (gid_t) -1) {
+ c->fsgid = (gid_t) item->creds.fsgid;
+ c->mask |= SD_BUS_CREDS_FSGID;
}
break;
@@ -581,6 +622,19 @@ static int bus_get_name_creds_kdbus(
cmd->size = size;
kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->flags);
+ /* If augmentation is on, and the bus doesn't didn't allow us
+ * to get the bits we want, then ask for the PID/TID so that we
+ * can read the rest from /proc. */
+ if ((mask & SD_BUS_CREDS_AUGMENT) &&
+ (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
+ SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+ SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
+ SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
+ SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
+ SD_BUS_CREDS_SELINUX_CONTEXT|
+ SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
+ cmd->flags |= KDBUS_ATTACH_PIDS;
+
r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
if (r < 0)
return -errno;
@@ -615,6 +669,10 @@ static int bus_get_name_creds_kdbus(
if (r < 0)
goto fail;
+ r = bus_creds_add_more(c, mask, 0, 0);
+ if (r < 0)
+ goto fail;
+
if (creds) {
*creds = c;
c = NULL;
@@ -673,11 +731,17 @@ static int bus_get_name_creds_dbus1(
c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
}
- if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_GID|
- SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
- SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
- SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
- SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) {
+ if ((mask & SD_BUS_CREDS_PID) ||
+ ((mask & SD_BUS_CREDS_AUGMENT) &&
+ (mask & (SD_BUS_CREDS_PID_STARTTIME|
+ SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
+ SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+ SD_BUS_CREDS_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
+ SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
+ SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
+ SD_BUS_CREDS_SELINUX_CONTEXT|
+ SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))) {
+
uint32_t u;
r = sd_bus_call_method(
@@ -781,7 +845,7 @@ _public_ int sd_bus_get_name_creds(
assert_return(bus, -EINVAL);
assert_return(name, -EINVAL);
- assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
+ assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
assert_return(mask == 0 || creds, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
assert_return(service_name_is_valid(name), -EINVAL);
@@ -802,7 +866,7 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
int r;
assert_return(bus, -EINVAL);
- assert_return(mask <= _SD_BUS_CREDS_ALL, -ENOTSUP);
+ assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -ENOTSUP);
assert_return(ret, -EINVAL);
assert_return(!bus_pid_changed(bus), -ECHILD);
@@ -837,7 +901,21 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
struct kdbus_info *creator_info;
cmd.size = sizeof(cmd);
- cmd.flags = _KDBUS_ATTACH_ALL;
+ kdbus_translate_attach_flags(mask, (uint64_t*) &cmd.flags);
+
+ /* If augmentation is on, and the bus doesn't didn't allow us
+ * to get the bits we want, then ask for the PID/TID so that we
+ * can read the rest from /proc. */
+ if ((mask & SD_BUS_CREDS_AUGMENT) &&
+ (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
+ SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
+ SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
+ SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
+ SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
+ SD_BUS_CREDS_SELINUX_CONTEXT|
+ SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
+ cmd.flags |= KDBUS_ATTACH_PIDS;
+
r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
if (r < 0)
return -errno;
@@ -849,12 +927,12 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
if (r < 0)
return r;
- } else {
- r = bus_creds_add_more(c, mask, pid, 0);
- if (r < 0)
- return r;
}
+ r = bus_creds_add_more(c, mask, pid, 0);
+ if (r < 0)
+ return r;
+
*ret = c;
c = NULL;
return 0;
diff --git a/src/libsystemd/sd-bus/bus-convenience.c b/src/libsystemd/sd-bus/bus-convenience.c
index 8081a2f9c0..ae0f4fa217 100644
--- a/src/libsystemd/sd-bus/bus-convenience.c
+++ b/src/libsystemd/sd-bus/bus-convenience.c
@@ -476,6 +476,7 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
uid_t our_uid;
+ bool know_caps = false;
int r;
assert_return(call, -EINVAL);
@@ -486,21 +487,21 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability)
if (!BUS_IS_OPEN(call->bus->state))
return -ENOTCONN;
- /* We only trust the effective capability set if this is
- * kdbus. On classic dbus1 we cannot retrieve the value
- * without races. Since this function is supposed to be useful
- * for authentication decision we hence avoid requesting and
- * using that information. */
- if (call->bus->is_kernel && capability >= 0) {
- r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
+ if (capability >= 0) {
+ r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
if (r < 0)
return r;
+ /* Note that not even on kdbus we might have the caps
+ * field, due to faked identities, or namespace
+ * translation issues. */
r = sd_bus_creds_has_effective_cap(creds, capability);
if (r > 0)
return 1;
+ if (r == 0)
+ know_caps = true;
} else {
- r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID, &creds);
+ r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
if (r < 0)
return r;
}
@@ -508,10 +509,14 @@ _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability)
/* Now, check the UID, but only if the capability check wasn't
* sufficient */
our_uid = getuid();
- if (our_uid != 0 || !call->bus->is_kernel || capability < 0) {
+ if (our_uid != 0 || !know_caps || capability < 0) {
uid_t sender_uid;
- r = sd_bus_creds_get_uid(creds, &sender_uid);
+ /* Try to use the EUID, if we have it. */
+ r = sd_bus_creds_get_euid(creds, &sender_uid);
+ if (r < 0)
+ r = sd_bus_creds_get_uid(creds, &sender_uid);
+
if (r >= 0) {
/* Sender has same UID as us, then let's grant access */
if (sender_uid == our_uid)
diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c
index d27ef1edbf..02a73725c6 100644
--- a/src/libsystemd/sd-bus/bus-creds.c
+++ b/src/libsystemd/sd-bus/bus-creds.c
@@ -141,7 +141,7 @@ _public_ int sd_bus_creds_new_from_pid(sd_bus_creds **ret, pid_t pid, uint64_t m
if (!c)
return -ENOMEM;
- r = bus_creds_add_more(c, mask, pid, 0);
+ r = bus_creds_add_more(c, mask | SD_BUS_CREDS_AUGMENT, pid, 0);
if (r < 0) {
sd_bus_creds_unref(c);
return r;
@@ -169,6 +169,40 @@ _public_ int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid) {
return 0;
}
+_public_ int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid) {
+ assert_return(c, -EINVAL);
+ assert_return(euid, -EINVAL);
+
+ if (!(c->mask & SD_BUS_CREDS_EUID))
+ return -ENODATA;
+
+ *euid = c->euid;
+ return 0;
+}
+
+_public_ int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid) {
+ assert_return(c, -EINVAL);
+ assert_return(suid, -EINVAL);
+
+ if (!(c->mask & SD_BUS_CREDS_SUID))
+ return -ENODATA;
+
+ *suid = c->suid;
+ return 0;
+}
+
+
+_public_ int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid) {
+ assert_return(c, -EINVAL);
+ assert_return(fsuid, -EINVAL);
+
+ if (!(c->mask & SD_BUS_CREDS_FSUID))
+ return -ENODATA;
+
+ *fsuid = c->fsuid;
+ return 0;
+}
+
_public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
assert_return(c, -EINVAL);
assert_return(gid, -EINVAL);
@@ -180,6 +214,41 @@ _public_ int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid) {
return 0;
}
+
+_public_ int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid) {
+ assert_return(c, -EINVAL);
+ assert_return(egid, -EINVAL);
+
+ if (!(c->mask & SD_BUS_CREDS_EGID))
+ return -ENODATA;
+
+ *egid = c->egid;
+ return 0;
+}
+
+_public_ int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid) {
+ assert_return(c, -EINVAL);
+ assert_return(sgid, -EINVAL);
+
+ if (!(c->mask & SD_BUS_CREDS_SGID))
+ return -ENODATA;
+
+ *sgid = c->sgid;
+ return 0;
+}
+
+
+_public_ int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid) {
+ assert_return(c, -EINVAL);
+ assert_return(fsgid, -EINVAL);
+
+ if (!(c->mask & SD_BUS_CREDS_FSGID))
+ return -ENODATA;
+
+ *fsgid = c->fsgid;
+ return 0;
+}
+
_public_ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid) {
assert_return(c, -EINVAL);
assert_return(pid, -EINVAL);
@@ -581,6 +650,9 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
assert(c);
assert(c->allocated);
+ if (!(mask & SD_BUS_CREDS_AUGMENT))
+ return 0;
+
missing = mask & ~c->mask;
if (missing == 0)
return 0;
@@ -596,98 +668,120 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
if (pid <= 0)
return 0;
- if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID |
+ if (pid > 0) {
+ c->pid = pid;
+ c->mask |= SD_BUS_CREDS_PID;
+ }
+
+ if (tid > 0) {
+ c->tid = tid;
+ c->mask |= SD_BUS_CREDS_TID;
+ }
+
+ if (missing & (SD_BUS_CREDS_UID | SD_BUS_CREDS_EUID | SD_BUS_CREDS_SUID | SD_BUS_CREDS_FSUID |
+ SD_BUS_CREDS_GID | SD_BUS_CREDS_EGID | SD_BUS_CREDS_SGID | SD_BUS_CREDS_FSGID |
SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_INHERITABLE_CAPS |
SD_BUS_CREDS_PERMITTED_CAPS | SD_BUS_CREDS_BOUNDING_CAPS)) {
_cleanup_fclose_ FILE *f = NULL;
- char line[LINE_MAX];
const char *p;
p = procfs_file_alloca(pid, "status");
f = fopen(p, "re");
- if (!f)
- return errno == ENOENT ? -ESRCH : -errno;
-
- FOREACH_LINE(line, f, return -errno) {
- truncate_nl(line);
-
- if (missing & SD_BUS_CREDS_UID) {
- p = startswith(line, "Uid:");
- if (p) {
- unsigned long uid;
-
- p += strspn(p, WHITESPACE);
- if (sscanf(p, "%lu", &uid) != 1)
- return -EIO;
-
- c->uid = (uid_t) uid;
- c->mask |= SD_BUS_CREDS_UID;
- continue;
+ if (!f) {
+ if (errno == ENOENT)
+ return -ESRCH;
+ else if (errno != EPERM && errno != EACCES)
+ return -errno;
+ } else {
+ char line[LINE_MAX];
+
+ FOREACH_LINE(line, f, return -errno) {
+ truncate_nl(line);
+
+ if (missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID)) {
+ p = startswith(line, "Uid:");
+ if (p) {
+ unsigned long uid, euid, suid, fsuid;
+
+ p += strspn(p, WHITESPACE);
+ if (sscanf(p, "%lu %lu %lu %lu", &uid, &euid, &suid, &fsuid) != 4)
+ return -EIO;
+
+ c->uid = (uid_t) uid;
+ c->euid = (uid_t) euid;
+ c->suid = (uid_t) suid;
+ c->fsuid = (uid_t) fsuid;
+ c->mask |= missing & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID);
+ continue;
+ }
}
- }
-
- if (missing & SD_BUS_CREDS_GID) {
- p = startswith(line, "Gid:");
- if (p) {
- unsigned long gid;
-
- p += strspn(p, WHITESPACE);
- if (sscanf(p, "%lu", &gid) != 1)
- return -EIO;
- c->gid = (uid_t) gid;
- c->mask |= SD_BUS_CREDS_GID;
- continue;
+ if (missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) {
+ p = startswith(line, "Gid:");
+ if (p) {
+ unsigned long gid, egid, sgid, fsgid;
+
+ p += strspn(p, WHITESPACE);
+ if (sscanf(p, "%lu %lu %lu %lu", &gid, &egid, &sgid, &fsgid) != 4)
+ return -EIO;
+
+ c->gid = (gid_t) gid;
+ c->egid = (gid_t) egid;
+ c->sgid = (gid_t) sgid;
+ c->fsgid = (gid_t) fsgid;
+ c->mask |= missing & (SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID);
+ continue;
+ }
}
- }
- if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
- p = startswith(line, "CapEff:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
- if (r < 0)
- return r;
+ if (missing & SD_BUS_CREDS_EFFECTIVE_CAPS) {
+ p = startswith(line, "CapEff:");
+ if (p) {
+ r = parse_caps(c, CAP_OFFSET_EFFECTIVE, p);
+ if (r < 0)
+ return r;
- c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
- continue;
+ c->mask |= SD_BUS_CREDS_EFFECTIVE_CAPS;
+ continue;
+ }
}
- }
- if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
- p = startswith(line, "CapPrm:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
- if (r < 0)
- return r;
+ if (missing & SD_BUS_CREDS_PERMITTED_CAPS) {
+ p = startswith(line, "CapPrm:");
+ if (p) {
+ r = parse_caps(c, CAP_OFFSET_PERMITTED, p);
+ if (r < 0)
+ return r;
- c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
- continue;
+ c->mask |= SD_BUS_CREDS_PERMITTED_CAPS;
+ continue;
+ }
}
- }
- if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
- p = startswith(line, "CapInh:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
- if (r < 0)
- return r;
+ if (missing & SD_BUS_CREDS_INHERITABLE_CAPS) {
+ p = startswith(line, "CapInh:");
+ if (p) {
+ r = parse_caps(c, CAP_OFFSET_INHERITABLE, p);
+ if (r < 0)
+ return r;
- c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
- continue;
+ c->mask |= SD_BUS_CREDS_INHERITABLE_CAPS;
+ continue;
+ }
}
- }
- if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
- p = startswith(line, "CapBnd:");
- if (p) {
- r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
- if (r < 0)
- return r;
+ if (missing & SD_BUS_CREDS_BOUNDING_CAPS) {
+ p = startswith(line, "CapBnd:");
+ if (p) {
+ r = parse_caps(c, CAP_OFFSET_BOUNDING, p);
+ if (r < 0)
+ return r;
- c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
- continue;
+ c->mask |= SD_BUS_CREDS_BOUNDING_CAPS;
+ continue;
+ }
}
}
}
@@ -697,11 +791,13 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
unsigned long long st;
r = get_starttime_of_pid(pid, &st);
- if (r < 0)
- return r;
-
- c->pid_starttime = ((usec_t) st * USEC_PER_SEC) / (usec_t) sysconf(_SC_CLK_TCK);
- c->mask |= SD_BUS_CREDS_PID_STARTTIME;
+ if (r < 0) {
+ if (r != -EPERM && r != -EACCES)
+ return r;
+ } else {
+ c->pid_starttime = ((usec_t) st * USEC_PER_SEC) / (usec_t) sysconf(_SC_CLK_TCK);
+ c->mask |= SD_BUS_CREDS_PID_STARTTIME;
+ }
}
if (missing & SD_BUS_CREDS_SELINUX_CONTEXT) {
@@ -709,26 +805,29 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
p = procfs_file_alloca(pid, "attr/current");
r = read_one_line_file(p, &c->label);
- if (r < 0 && r != -ENOENT && r != -EINVAL)
- return r;
- else if (r >= 0)
+ if (r < 0) {
+ if (r != -ENOENT && r != -EINVAL && r != -EPERM && r != -EACCES)
+ return r;
+ } else
c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
}
if (missing & SD_BUS_CREDS_COMM) {
r = get_process_comm(pid, &c->comm);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_COMM;
+ if (r < 0) {
+ if (r != -EPERM && r != -EACCES)
+ return r;
+ } else
+ c->mask |= SD_BUS_CREDS_COMM;
}
if (missing & SD_BUS_CREDS_EXE) {
r = get_process_exe(pid, &c->exe);
- if (r < 0)
- return r;
-
- c->mask |= SD_BUS_CREDS_EXE;
+ if (r < 0) {
+ if (r != -EPERM && r != -EACCES)
+ return r;
+ } else
+ c->mask |= SD_BUS_CREDS_EXE;
}
if (missing & SD_BUS_CREDS_CMDLINE) {
@@ -736,14 +835,18 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
p = procfs_file_alloca(pid, "cmdline");
r = read_full_file(p, &c->cmdline, &c->cmdline_size);
- if (r < 0)
- return r;
-
- if (c->cmdline_size == 0) {
- free(c->cmdline);
- c->cmdline = NULL;
- } else
- c->mask |= SD_BUS_CREDS_CMDLINE;
+ if (r < 0) {
+ if (r == -ENOENT)
+ return -ESRCH;
+ if (r != -EPERM && r != -EACCES)
+ return r;
+ } else {
+ if (c->cmdline_size == 0) {
+ free(c->cmdline);
+ c->cmdline = NULL;
+ } else
+ c->mask |= SD_BUS_CREDS_CMDLINE;
+ }
}
if (tid > 0 && (missing & SD_BUS_CREDS_TID_COMM)) {
@@ -753,38 +856,45 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) {
return -ENOMEM;
r = read_one_line_file(p, &c->tid_comm);
- if (r < 0)
- return r == -ENOENT ? -ESRCH : r;
-
- c->mask |= SD_BUS_CREDS_TID_COMM;
+ if (r < 0) {
+ if (r == -ENOENT)
+ return -ESRCH;
+ if (r != -EPERM && r != -EACCES)
+ return r;
+ } else
+ c->mask |= SD_BUS_CREDS_TID_COMM;
}
if (missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID)) {
r = cg_pid_get_path(NULL, pid, &c->cgroup);
- if (r < 0)
- return r;
-
- r = cg_get_root_path(&c->cgroup_root);
- if (r < 0)
- return r;
-
- c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
+ if (r < 0) {
+ if (r != -EPERM && r != -EACCES)
+ return r;
+ } else {
+ r = cg_get_root_path(&c->cgroup_root);
+ if (r < 0)
+ return r;
+
+ c->mask |= missing & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID);
+ }
}
if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) {
r = audit_session_from_pid(pid, &c->audit_session_id);
- if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != -ENOENT)
- return r;
- else if (r >= 0)
+ if (r < 0) {
+ if (r != -ENOTSUP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
+ return r;
+ } else
c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
}
if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
r = audit_loginuid_from_pid(pid, &c->audit_login_uid);
- if (r < 0 && r != -ENOTSUP && r != -ENXIO && r != -ENOENT)
- return r;
- else if (r >= 0)
+ if (r < 0) {
+ if (r != -ENOTSUP && r != -ENXIO && r != -ENOENT && r != -EPERM && r != -EACCES)
+ return r;
+ } else
c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
}
@@ -798,8 +908,9 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
assert(c);
assert(ret);
- if ((mask & ~c->mask) == 0) {
- /* There's already all data we need. */
+ if ((mask & ~c->mask) == 0 || (!(mask & SD_BUS_CREDS_AUGMENT))) {
+ /* There's already all data we need, or augmentation
+ * wasn't turned on. */
*ret = sd_bus_creds_ref(c);
return 0;
@@ -816,11 +927,41 @@ int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret)
n->mask |= SD_BUS_CREDS_UID;
}
+ if (c->mask & mask & SD_BUS_CREDS_EUID) {
+ n->euid = c->euid;
+ n->mask |= SD_BUS_CREDS_EUID;
+ }
+
+ if (c->mask & mask & SD_BUS_CREDS_SUID) {
+ n->suid = c->suid;
+ n->mask |= SD_BUS_CREDS_SUID;
+ }
+
+ if (c->mask & mask & SD_BUS_CREDS_FSUID) {
+ n->fsuid = c->fsuid;
+ n->mask |= SD_BUS_CREDS_FSUID;
+ }
+
if (c->mask & mask & SD_BUS_CREDS_GID) {
n->gid = c->gid;
n->mask |= SD_BUS_CREDS_GID;
}
+ if (c->mask & mask & SD_BUS_CREDS_EGID) {
+ n->egid = c->egid;
+ n->mask |= SD_BUS_CREDS_EGID;
+ }
+
+ if (c->mask & mask & SD_BUS_CREDS_SGID) {
+ n->sgid = c->sgid;
+ n->mask |= SD_BUS_CREDS_SGID;
+ }
+
+ if (c->mask & mask & SD_BUS_CREDS_FSGID) {
+ n->fsgid = c->fsgid;
+ n->mask |= SD_BUS_CREDS_FSGID;
+ }
+
if (c->mask & mask & SD_BUS_CREDS_PID) {
n->pid = c->pid;
n->mask |= SD_BUS_CREDS_PID;
diff --git a/src/libsystemd/sd-bus/bus-creds.h b/src/libsystemd/sd-bus/bus-creds.h
index cf1f611237..15821a57d2 100644
--- a/src/libsystemd/sd-bus/bus-creds.h
+++ b/src/libsystemd/sd-bus/bus-creds.h
@@ -32,7 +32,14 @@ struct sd_bus_creds {
uint64_t mask;
uid_t uid;
+ uid_t euid;
+ uid_t suid;
+ uid_t fsuid;
gid_t gid;
+ gid_t egid;
+ gid_t sgid;
+ gid_t fsgid;
+
pid_t pid;
usec_t pid_starttime;
pid_t tid;
diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c
index 5e96b00263..d6e5546053 100644
--- a/src/libsystemd/sd-bus/bus-dump.c
+++ b/src/libsystemd/sd-bus/bus-dump.c
@@ -360,15 +360,32 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f, bool terse) {
fprintf(f, "%sPIDStartTime=%s"USEC_FMT"%s", prefix, color, c->pid_starttime, suffix);
if (c->mask & SD_BUS_CREDS_TID)
fprintf(f, "%sTID=%s"PID_FMT"%s", prefix, color, c->tid, suffix);
+
+ if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))))
+ fputs("\n", f);
+
if (c->mask & SD_BUS_CREDS_UID)
fprintf(f, "%sUID=%s"UID_FMT"%s", prefix, color, c->uid, suffix);
+ if (c->mask & SD_BUS_CREDS_EUID)
+ fprintf(f, "%sEUID=%s"UID_FMT"%s", prefix, color, c->euid, suffix);
+ if (c->mask & SD_BUS_CREDS_SUID)
+ fprintf(f, "%sSUID=%s"UID_FMT"%s", prefix, color, c->suid, suffix);
+ if (c->mask & SD_BUS_CREDS_FSUID)
+ fprintf(f, "%sFSUID=%s"UID_FMT"%s", prefix, color, c->fsuid, suffix);
r = sd_bus_creds_get_owner_uid(c, &owner);
if (r >= 0)
fprintf(f, "%sOwnerUID=%s"UID_FMT"%s", prefix, color, owner, suffix);
if (c->mask & SD_BUS_CREDS_GID)
fprintf(f, "%sGID=%s"GID_FMT"%s", prefix, color, c->gid, suffix);
-
- if (terse && ((c->mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID|SD_BUS_CREDS_UID|SD_BUS_CREDS_GID)) || r >= 0))
+ if (c->mask & SD_BUS_CREDS_EGID)
+ fprintf(f, "%sEGID=%s"GID_FMT"%s", prefix, color, c->egid, suffix);
+ if (c->mask & SD_BUS_CREDS_SGID)
+ fprintf(f, "%sSGID=%s"GID_FMT"%s", prefix, color, c->sgid, suffix);
+ if (c->mask & SD_BUS_CREDS_FSGID)
+ fprintf(f, "%sFSGID=%s"GID_FMT"%s", prefix, color, c->fsgid, suffix);
+
+ if (terse && ((c->mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
+ SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID)) || r >= 0))
fputs("\n", f);
if (c->mask & SD_BUS_CREDS_COMM)
diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h
index f6b0211c2c..977b3407ba 100644
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -206,6 +206,7 @@ struct sd_bus {
bool nodes_modified:1;
bool trusted:1;
bool fake_creds_valid:1;
+ bool fake_pids_valid:1;
bool manual_peer_interface:1;
bool is_system:1;
bool is_user:1;
@@ -306,6 +307,7 @@ struct sd_bus {
pid_t tid;
struct kdbus_creds fake_creds;
+ struct kdbus_pids fake_pids;
char *fake_label;
char *cgroup_root;
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c
index afac3b6bcc..79d29dc119 100644
--- a/src/libsystemd/sd-bus/bus-kernel.c
+++ b/src/libsystemd/sd-bus/bus-kernel.c
@@ -513,28 +513,75 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
break;
}
- case KDBUS_ITEM_CREDS:
- /* UID/GID/PID are always valid */
- m->creds.uid = (uid_t) d->creds.uid;
- m->creds.gid = (gid_t) d->creds.gid;
- m->creds.pid = (pid_t) d->creds.pid;
- m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID) & bus->creds_mask;
-
- /* The PID starttime/TID might be missing
- * however, when the data is faked by some
- * data bus proxy and it lacks that
- * information about the real client since
- * SO_PEERCRED is used for that */
-
- if (d->creds.starttime > 0) {
- m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
+ case KDBUS_ITEM_PIDS:
+
+ /* The PID starttime/TID might be missing,
+ * when the data is faked by some data bus
+ * proxy and it lacks that information about
+ * the real client since SO_PEERCRED is used
+ * for that. */
+
+ if (d->pids.pid > 0) {
+ m->creds.pid = (pid_t) d->pids.pid;
+ m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
+ }
+
+ if (d->pids.starttime > 0) {
+ m->creds.pid_starttime = d->pids.starttime / NSEC_PER_USEC;
m->creds.mask |= SD_BUS_CREDS_PID_STARTTIME & bus->creds_mask;
}
- if (d->creds.tid > 0) {
- m->creds.tid = (pid_t) d->creds.tid;
+ if (d->pids.tid > 0) {
+ m->creds.tid = (pid_t) d->pids.tid;
m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
}
+
+ break;
+
+ case KDBUS_ITEM_CREDS:
+
+ /* EUID/SUID/FSUID/EGID/SGID/FSGID might be missing too (see above). */
+
+ if ((uid_t) d->creds.uid != (uid_t) -1) {
+ m->creds.uid = (uid_t) d->creds.uid;
+ m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
+ }
+
+ if ((uid_t) d->creds.euid != (uid_t) -1) {
+ m->creds.euid = (uid_t) d->creds.euid;
+ m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
+ }
+
+ if ((uid_t) d->creds.suid != (uid_t) -1) {
+ m->creds.suid = (uid_t) d->creds.suid;
+ m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
+ }
+
+ if ((uid_t) d->creds.fsuid != (uid_t) -1) {
+ m->creds.fsuid = (uid_t) d->creds.fsuid;
+ m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
+ }
+
+ if ((gid_t) d->creds.gid != (gid_t) -1) {
+ m->creds.gid = (gid_t) d->creds.gid;
+ m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
+ }
+
+ if ((gid_t) d->creds.egid != (gid_t) -1) {
+ m->creds.egid = (gid_t) d->creds.egid;
+ m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
+ }
+
+ if ((gid_t) d->creds.sgid != (gid_t) -1) {
+ m->creds.sgid = (gid_t) d->creds.sgid;
+ m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
+ }
+
+ if ((gid_t) d->creds.fsgid != (gid_t) -1) {
+ m->creds.fsgid = (gid_t) d->creds.fsgid;
+ m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
+ }
+
break;
case KDBUS_ITEM_TIMESTAMP:
@@ -724,6 +771,9 @@ int bus_kernel_take_fd(sd_bus *b) {
if (b->fake_creds_valid)
sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
+ if (b->fake_pids_valid)
+ sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
+
if (b->fake_label) {
l = strlen(b->fake_label);
sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
@@ -751,6 +801,14 @@ int bus_kernel_take_fd(sd_bus *b) {
item = KDBUS_ITEM_NEXT(item);
}
+ if (b->fake_pids_valid) {
+ item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
+ item->type = KDBUS_ITEM_PIDS;
+ item->pids = b->fake_pids;
+
+ item = KDBUS_ITEM_NEXT(item);
+ }
+
if (b->fake_label) {
item->size = offsetof(struct kdbus_item, str) + l + 1;
item->type = KDBUS_ITEM_SECLABEL;
@@ -1237,9 +1295,13 @@ int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
assert(kdbus_mask);
- if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
+ if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
+ SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
m |= KDBUS_ATTACH_CREDS;
+ if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
+ m |= KDBUS_ATTACH_PIDS;
+
if (mask & SD_BUS_CREDS_COMM)
m |= KDBUS_ATTACH_PID_COMM;
diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h
index e3a80c352d..65266ee212 100644
--- a/src/libsystemd/sd-bus/kdbus.h
+++ b/src/libsystemd/sd-bus/kdbus.h
@@ -58,22 +58,43 @@ struct kdbus_notify_name_change {
/**
* struct kdbus_creds - process credentials
* @uid: User ID
+ * @euid: Effective UID
+ * @suid: Saved UID
+ * @fsuid: Filesystem UID
* @gid: Group ID
- * @pid: Process ID
- * @tid: Thread ID
- * @starttime: Starttime of the process
- *
- * The starttime of the process PID. This is useful to detect PID overruns
- * from the client side. i.e. if you use the PID to look something up in
- * /proc/$PID/ you can afterwards check the starttime field of it, to ensure
- * you didn't run into a PID overrun.
+ * @egid: Effective GID
+ * @sgid: Saved GID
+ * @fsgid: Filesystem GID
*
* Attached to:
* KDBUS_ITEM_CREDS
*/
struct kdbus_creds {
__u64 uid;
+ __u64 euid;
+ __u64 suid;
+ __u64 fsuid;
__u64 gid;
+ __u64 egid;
+ __u64 sgid;
+ __u64 fsgid;
+};
+
+/**
+ * struct kdbus_pids - process identifiers
+ * @pid: Process ID
+ * @tid: Thread ID
+ * @starttime: Starttime of the process
+ *
+ * The PID, TID and starttime of a process. The start tmie is useful to detect
+ * PID overruns from the client side. i.e. if you use the PID to look something
+ * up in /proc/$PID/ you can afterwards check the starttime field of it, to
+ * ensure you didn't run into a PID overrun.
+ *
+ * Attached to:
+ * KDBUS_ITEM_PIDS
+ */
+struct kdbus_pids {
__u64 pid;
__u64 tid;
__u64 starttime;
@@ -229,14 +250,19 @@ struct kdbus_policy_access {
* @KDBUS_ITEM_NAME: Well-know name with flags
* @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items
* @KDBUS_ITEM_TIMESTAMP: Timestamp
- * @KDBUS_ITEM_CREDS: Process credential
+ * @KDBUS_ITEM_CREDS: Process credentials
+ * @KDBUS_ITEM_PIDS: Process identifiers
* @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups
* @KDBUS_ITEM_OWNED_NAME: A name owned by the associated
* connection
* @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier
+ * (Don't trust this, see below.)
* @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier
+ * (Don't trust this, see below.)
* @KDBUS_ITEM_EXE: The path of the executable
+ * (Don't trust this, see below.)
* @KDBUS_ITEM_CMDLINE: The process command line
+ * (Don't trust this, see below.)
* @KDBUS_ITEM_CGROUP: The croup membership
* @KDBUS_ITEM_CAPS: The process capabilities
* @KDBUS_ITEM_SECLABEL: The security label
@@ -253,6 +279,12 @@ struct kdbus_policy_access {
* @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change
* @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached
* @KDBUS_ITEM_REPLY_DEAD: Destination died
+ *
+ * N.B: The process and thread COMM fields, as well as the CMDLINE and
+ * EXE fields may be altered by unprivileged processes und should
+ * hence *not* used for security decisions. Peers should make use of
+ * these items only for informational purposes, such as generating log
+ * records.
*/
enum kdbus_item_type {
_KDBUS_ITEM_NULL,
@@ -275,6 +307,7 @@ enum kdbus_item_type {
_KDBUS_ITEM_ATTACH_BASE = 0x1000,
KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE,
KDBUS_ITEM_CREDS,
+ KDBUS_ITEM_PIDS,
KDBUS_ITEM_AUXGROUPS,
KDBUS_ITEM_OWNED_NAME,
KDBUS_ITEM_TID_COMM,
@@ -336,6 +369,7 @@ struct kdbus_item {
__u64 id;
struct kdbus_vec vec;
struct kdbus_creds creds;
+ struct kdbus_pids pids;
struct kdbus_audit audit;
struct kdbus_caps caps;
struct kdbus_timestamp timestamp;
@@ -455,6 +489,10 @@ enum kdbus_recv_flags {
* @offset: Returned offset in the pool where the message is
* stored. The user must use KDBUS_CMD_FREE to free
* the allocated memory.
+ * @dropped_msgs: In case the KDBUS_CMD_MSG_RECV ioctl returns
+ * -EOVERFLOW, this field will contain the number of
+ * broadcast messages that have been lost since the
+ * last call.
*
* This struct is used with the KDBUS_CMD_MSG_RECV ioctl.
*/
@@ -462,7 +500,10 @@ struct kdbus_cmd_recv {
__u64 flags;
__u64 kernel_flags;
__s64 priority;
- __u64 offset;
+ union {
+ __u64 offset;
+ __u64 dropped_msgs;
+ };
} __attribute__((aligned(8)));
/**
@@ -547,6 +588,7 @@ enum kdbus_hello_flags {
* enum kdbus_attach_flags - flags for metadata attachments
* @KDBUS_ATTACH_TIMESTAMP: Timestamp
* @KDBUS_ATTACH_CREDS: Credentials
+ * @KDBUS_ATTACH_PIDS: PIDs
* @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups
* @KDBUS_ATTACH_NAMES: Well-known names
* @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID
@@ -565,18 +607,19 @@ enum kdbus_hello_flags {
enum kdbus_attach_flags {
KDBUS_ATTACH_TIMESTAMP = 1ULL << 0,
KDBUS_ATTACH_CREDS = 1ULL << 1,
- KDBUS_ATTACH_AUXGROUPS = 1ULL << 2,
- KDBUS_ATTACH_NAMES = 1ULL << 3,
- KDBUS_ATTACH_TID_COMM = 1ULL << 4,
- KDBUS_ATTACH_PID_COMM = 1ULL << 5,
- KDBUS_ATTACH_EXE = 1ULL << 6,
- KDBUS_ATTACH_CMDLINE = 1ULL << 7,
- KDBUS_ATTACH_CGROUP = 1ULL << 8,
- KDBUS_ATTACH_CAPS = 1ULL << 9,
- KDBUS_ATTACH_SECLABEL = 1ULL << 10,
- KDBUS_ATTACH_AUDIT = 1ULL << 11,
- KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 12,
- _KDBUS_ATTACH_ALL = (1ULL << 13) - 1,
+ KDBUS_ATTACH_PIDS = 1ULL << 2,
+ KDBUS_ATTACH_AUXGROUPS = 1ULL << 3,
+ KDBUS_ATTACH_NAMES = 1ULL << 4,
+ KDBUS_ATTACH_TID_COMM = 1ULL << 5,
+ KDBUS_ATTACH_PID_COMM = 1ULL << 6,
+ KDBUS_ATTACH_EXE = 1ULL << 7,
+ KDBUS_ATTACH_CMDLINE = 1ULL << 8,
+ KDBUS_ATTACH_CGROUP = 1ULL << 9,
+ KDBUS_ATTACH_CAPS = 1ULL << 10,
+ KDBUS_ATTACH_SECLABEL = 1ULL << 11,
+ KDBUS_ATTACH_AUDIT = 1ULL << 12,
+ KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13,
+ _KDBUS_ATTACH_ALL = (1ULL << 14) - 1,
_KDBUS_ATTACH_ANY = ~0ULL
};
@@ -619,8 +662,8 @@ struct kdbus_cmd_hello {
/**
* enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,EP,NS}_MAKE
- * @KDBUS_MAKE_ACCESS_GROUP: Make the device node group-accessible
- * @KDBUS_MAKE_ACCESS_WORLD: Make the device node world-accessible
+ * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible
+ * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible
*/
enum kdbus_make_flags {
KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0,
@@ -713,7 +756,7 @@ enum kdbus_name_list_flags {
/**
* struct kdbus_cmd_name_list - request a list of name entries
* @flags: Flags for the query (KDBUS_NAME_LIST_*),
- * userspace → kernel
+ * userspace → kernel
* @kernel_flags: Supported flags for queries, kernel → userspace
* @offset: The returned offset in the caller's pool buffer.
* The user must use KDBUS_CMD_FREE to free the
@@ -834,16 +877,16 @@ struct kdbus_cmd_match {
/**
* Ioctl API
- * KDBUS_CMD_BUS_MAKE: After opening the "control" device node, this
- * command creates a new bus with the specified
+ * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command
+ * creates a new bus with the specified
* name. The bus is immediately shut down and
- * cleaned up when the opened "control" device node
- * is closed.
+ * cleaned up when the opened file descriptor is
+ * closed.
* KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to
* the bus. Such endpoints usually carry a more
* restrictive policy and grant restricted access
* to specific applications.
- * KDBUS_CMD_HELLO: By opening the bus device node a connection is
+ * KDBUS_CMD_HELLO: By opening the bus node, a connection is
* created. After a HELLO the opened connection
* becomes an active peer on the bus.
* KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
index b1a1f79d86..5aa8eacebb 100644
--- a/src/libsystemd/sd-bus/sd-bus.c
+++ b/src/libsystemd/sd-bus/sd-bus.c
@@ -1070,7 +1070,7 @@ _public_ int sd_bus_open(sd_bus **ret) {
/* We don't know whether the bus is trusted or not, so better
* be safe, and authenticate everything */
b->trusted = false;
- b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS;
+ b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS | KDBUS_ATTACH_PIDS;
r = sd_bus_start(b);
if (r < 0)
diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h
index 58a898080b..21d693b4bc 100644
--- a/src/systemd/sd-bus.h
+++ b/src/systemd/sd-bus.h
@@ -53,28 +53,35 @@ enum {
SD_BUS_CREDS_PID_STARTTIME = 1ULL << 1,
SD_BUS_CREDS_TID = 1ULL << 2,
SD_BUS_CREDS_UID = 1ULL << 3,
- SD_BUS_CREDS_GID = 1ULL << 4,
- SD_BUS_CREDS_COMM = 1ULL << 5,
- SD_BUS_CREDS_TID_COMM = 1ULL << 6,
- SD_BUS_CREDS_EXE = 1ULL << 7,
- SD_BUS_CREDS_CMDLINE = 1ULL << 8,
- SD_BUS_CREDS_CGROUP = 1ULL << 9,
- SD_BUS_CREDS_UNIT = 1ULL << 10,
- SD_BUS_CREDS_USER_UNIT = 1ULL << 11,
- SD_BUS_CREDS_SLICE = 1ULL << 12,
- SD_BUS_CREDS_SESSION = 1ULL << 13,
- SD_BUS_CREDS_OWNER_UID = 1ULL << 14,
- SD_BUS_CREDS_EFFECTIVE_CAPS = 1ULL << 15,
- SD_BUS_CREDS_PERMITTED_CAPS = 1ULL << 16,
- SD_BUS_CREDS_INHERITABLE_CAPS = 1ULL << 17,
- SD_BUS_CREDS_BOUNDING_CAPS = 1ULL << 18,
- SD_BUS_CREDS_SELINUX_CONTEXT = 1ULL << 19,
- SD_BUS_CREDS_AUDIT_SESSION_ID = 1ULL << 20,
- SD_BUS_CREDS_AUDIT_LOGIN_UID = 1ULL << 21,
- SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 22,
- SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 23,
- SD_BUS_CREDS_DESCRIPTION = 1ULL << 24,
- _SD_BUS_CREDS_ALL = (1ULL << 25) -1,
+ SD_BUS_CREDS_EUID = 1ULL << 4,
+ SD_BUS_CREDS_SUID = 1ULL << 5,
+ SD_BUS_CREDS_FSUID = 1ULL << 6,
+ SD_BUS_CREDS_GID = 1ULL << 7,
+ SD_BUS_CREDS_EGID = 1ULL << 8,
+ SD_BUS_CREDS_SGID = 1ULL << 9,
+ SD_BUS_CREDS_FSGID = 1ULL << 10,
+ SD_BUS_CREDS_COMM = 1ULL << 11,
+ SD_BUS_CREDS_TID_COMM = 1ULL << 12,
+ SD_BUS_CREDS_EXE = 1ULL << 13,
+ SD_BUS_CREDS_CMDLINE = 1ULL << 14,
+ SD_BUS_CREDS_CGROUP = 1ULL << 15,
+ SD_BUS_CREDS_UNIT = 1ULL << 16,
+ SD_BUS_CREDS_USER_UNIT = 1ULL << 17,
+ SD_BUS_CREDS_SLICE = 1ULL << 18,
+ SD_BUS_CREDS_SESSION = 1ULL << 19,
+ SD_BUS_CREDS_OWNER_UID = 1ULL << 20,
+ SD_BUS_CREDS_EFFECTIVE_CAPS = 1ULL << 21,
+ SD_BUS_CREDS_PERMITTED_CAPS = 1ULL << 22,
+ SD_BUS_CREDS_INHERITABLE_CAPS = 1ULL << 23,
+ SD_BUS_CREDS_BOUNDING_CAPS = 1ULL << 24,
+ SD_BUS_CREDS_SELINUX_CONTEXT = 1ULL << 25,
+ SD_BUS_CREDS_AUDIT_SESSION_ID = 1ULL << 26,
+ SD_BUS_CREDS_AUDIT_LOGIN_UID = 1ULL << 27,
+ SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 28,
+ SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 29,
+ SD_BUS_CREDS_DESCRIPTION = 1ULL << 30,
+ SD_BUS_CREDS_AUGMENT = 1ULL << 63, /* special flag, if on sd-bus will augment creds struct, in a potentially race-full way. */
+ _SD_BUS_CREDS_ALL = (1ULL << 31) -1,
};
enum {
@@ -305,7 +312,13 @@ int sd_bus_creds_get_pid(sd_bus_creds *c, pid_t *pid);
int sd_bus_creds_get_pid_starttime(sd_bus_creds *c, uint64_t *usec);
int sd_bus_creds_get_tid(sd_bus_creds *c, pid_t *tid);
int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid);
+int sd_bus_creds_get_euid(sd_bus_creds *c, uid_t *euid);
+int sd_bus_creds_get_suid(sd_bus_creds *c, uid_t *suid);
+int sd_bus_creds_get_fsuid(sd_bus_creds *c, uid_t *fsuid);
int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid);
+int sd_bus_creds_get_egid(sd_bus_creds *c, gid_t *egid);
+int sd_bus_creds_get_sgid(sd_bus_creds *c, gid_t *sgid);
+int sd_bus_creds_get_fsgid(sd_bus_creds *c, gid_t *fsgid);
int sd_bus_creds_get_comm(sd_bus_creds *c, const char **comm);
int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **comm);
int sd_bus_creds_get_exe(sd_bus_creds *c, const char **exe);