summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);