From 49b832c5b810f4d8bb59249ff25472fd670503dc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 30 Nov 2013 04:14:10 +0100 Subject: [PATCH] bus: include unique and well known names in credentials object --- TODO | 1 + src/core/service.c | 2 +- src/libsystemd-bus/bus-control.c | 449 ++++++++++++++------------ src/libsystemd-bus/bus-convenience.c | 4 +- src/libsystemd-bus/bus-creds.c | 83 +++-- src/libsystemd-bus/bus-creds.h | 10 +- src/libsystemd-bus/bus-dump.c | 23 +- src/libsystemd-bus/bus-kernel.c | 15 +- src/libsystemd-bus/bus-message.c | 6 + src/libsystemd-bus/busctl.c | 9 +- src/libsystemd-bus/libsystemd-bus.sym | 3 +- src/libsystemd-bus/sd-bus.c | 3 + src/shared/strv.c | 2 +- src/systemd/sd-bus.h | 26 +- 14 files changed, 371 insertions(+), 265 deletions(-) diff --git a/TODO b/TODO index 127994a80..ff162ea3f 100644 --- a/TODO +++ b/TODO @@ -135,6 +135,7 @@ Features: - support "const" properties as flag - add API to clone sd_bus_message objects - SD_BUS_COMMENT() macro for inclusion in vtables, syntax inspired by gdbus + - unelss configure option is specified refuse connecting and creating kdbus, so that we can break compat * sd-event - allow multiple signal handlers per signal diff --git a/src/core/service.c b/src/core/service.c index 10bf7cb5a..fcfeda738 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3678,7 +3678,7 @@ static void service_bus_name_owner_change( /* Try to acquire PID from bus service */ - r = sd_bus_get_owner(u->manager->api_bus, name, SD_BUS_CREDS_PID, NULL, &creds); + r = sd_bus_get_owner(u->manager->api_bus, name, SD_BUS_CREDS_PID, &creds); if (r >= 0) r = sd_bus_creds_get_pid(creds, &pid); if (r >= 0) { diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c index 1d1f6d0f3..9e815a6c9 100644 --- a/src/libsystemd-bus/bus-control.c +++ b/src/libsystemd-bus/bus-control.c @@ -251,24 +251,21 @@ _public_ int sd_bus_list_names(sd_bus *bus, char ***l) { return 0; } -static int sd_bus_get_owner_dbus( +static int bus_get_owner_dbus( sd_bus *bus, const char *name, uint64_t mask, - char **owner, sd_bus_creds **creds) { - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply_unique = NULL, *reply = NULL; _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; - _cleanup_free_ char *unique = NULL; + const char *unique = NULL; pid_t pid = 0; int r; /* Only query the owner if the caller wants to know it or if * the caller just wants to check whether a name exists */ - if (owner || mask == 0) { - const char *found; - + if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) { r = sd_bus_call_method( bus, "org.freedesktop.DBus", @@ -276,21 +273,15 @@ static int sd_bus_get_owner_dbus( "org.freedesktop.DBus", "GetNameOwner", NULL, - &reply, + &reply_unique, "s", name); if (r < 0) return r; - r = sd_bus_message_read(reply, "s", &found); + r = sd_bus_message_read(reply_unique, "s", &unique); if (r < 0) return r; - - unique = strdup(found); - if (!unique) - return -ENOMEM; - - reply = sd_bus_message_unref(reply); } if (mask != 0) { @@ -298,8 +289,19 @@ static int sd_bus_get_owner_dbus( if (!c) return -ENOMEM; - if ((mask & SD_BUS_CREDS_PID) || - mask & ~(SD_BUS_CREDS_PID|SD_BUS_CREDS_UID|SD_BUS_CREDS_SELINUX_CONTEXT)) { + if ((mask & SD_BUS_CREDS_UNIQUE_NAME) && unique) { + c->unique_name = strdup(unique); + if (!c->unique_name) + return -ENOMEM; + + 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)) { uint32_t u; r = sd_bus_call_method( @@ -311,7 +313,7 @@ static int sd_bus_get_owner_dbus( NULL, &reply, "s", - name); + unique ? unique : name); if (r < 0) return r; @@ -340,7 +342,7 @@ static int sd_bus_get_owner_dbus( NULL, &reply, "s", - name); + unique ? unique : name); if (r < 0) return r; @@ -367,7 +369,7 @@ static int sd_bus_get_owner_dbus( NULL, &reply, "s", - name); + unique ? unique : name); if (r < 0) return r; @@ -392,12 +394,225 @@ static int sd_bus_get_owner_dbus( c = NULL; } - if (owner) { - *owner = unique; - unique = NULL; + return 0; +} + +static int bus_get_owner_kdbus( + sd_bus *bus, + const char *name, + uint64_t mask, + sd_bus_creds **creds) { + + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; + struct kdbus_cmd_name_info *cmd; + struct kdbus_name_info *name_info; + struct kdbus_item *item; + size_t size; + uint64_t m, id; + int r; + + r = bus_kernel_parse_unique_name(name, &id); + if (r < 0) + return r; + if (r > 0) { + size = offsetof(struct kdbus_cmd_name_info, name); + cmd = alloca0(size); + cmd->id = id; + } else { + size = offsetof(struct kdbus_cmd_name_info, name) + strlen(name) + 1; + cmd = alloca0(size); + strcpy(cmd->name, name); } - return 0; + cmd->size = size; + + r = kdbus_translate_attach_flags(mask, (uint64_t*) &cmd->attach_flags); + if (r < 0) + return r; + + r = ioctl(bus->input_fd, KDBUS_CMD_NAME_INFO, cmd); + if (r < 0) + return -errno; + + name_info = (struct kdbus_name_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset); + + c = bus_creds_new(); + if (!c) + return -ENOMEM; + + if (mask & SD_BUS_CREDS_UNIQUE_NAME) { + if (asprintf(&c->unique_name, ":1.%llu", (unsigned long long) name_info->id) < 0) + return -ENOMEM; + + c->mask |= SD_BUS_CREDS_UNIQUE_NAME; + } + + KDBUS_PART_FOREACH(item, name_info, items) { + + switch (item->type) { + + case KDBUS_ITEM_CREDS: + m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID | + SD_BUS_CREDS_TID | SD_BUS_CREDS_PID_STARTTIME) & mask; + + if (m) { + c->uid = item->creds.uid; + c->pid = item->creds.pid; + c->gid = item->creds.gid; + c->tid = item->creds.tid; + c->pid_starttime = item->creds.starttime; + c->mask |= m; + } + break; + + case KDBUS_ITEM_PID_COMM: + if (mask & SD_BUS_CREDS_COMM) { + c->comm = strdup(item->str); + if (!c->comm) { + r = -ENOMEM; + goto fail; + } + + c->mask |= SD_BUS_CREDS_COMM; + } + break; + + case KDBUS_ITEM_TID_COMM: + if (mask & SD_BUS_CREDS_TID_COMM) { + c->tid_comm = strdup(item->str); + if (!c->tid_comm) { + r = -ENOMEM; + goto fail; + } + + c->mask |= SD_BUS_CREDS_TID_COMM; + } + break; + + case KDBUS_ITEM_EXE: + if (mask & SD_BUS_CREDS_EXE) { + c->exe = strdup(item->str); + if (!c->exe) { + r = -ENOMEM; + goto fail; + } + + c->mask |= SD_BUS_CREDS_EXE; + } + break; + + case KDBUS_ITEM_CMDLINE: + if (mask & SD_BUS_CREDS_CMDLINE) { + c->cmdline_size = item->size - KDBUS_PART_HEADER_SIZE; + c->cmdline = memdup(item->data, c->cmdline_size); + if (!c->cmdline) { + r = -ENOMEM; + goto fail; + } + + c->mask |= SD_BUS_CREDS_CMDLINE; + } + break; + + case KDBUS_ITEM_CGROUP: + m = (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) & mask; + + if (m) { + c->cgroup = strdup(item->str); + if (!c->cgroup) { + r = -ENOMEM; + goto fail; + } + + c->mask |= m; + } + break; + + case KDBUS_ITEM_CAPS: + m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS | + SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask; + + if (m) { + c->capability_size = item->size - KDBUS_PART_HEADER_SIZE; + c->capability = memdup(item->data, c->capability_size); + if (!c->capability) { + r = -ENOMEM; + goto fail; + } + + c->mask |= m; + } + break; + + case KDBUS_ITEM_SECLABEL: + if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) { + c->label = strdup(item->str); + if (!c->label) { + r = -ENOMEM; + goto fail; + } + + c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + break; + + case KDBUS_ITEM_AUDIT: + m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask; + + if (m) { + c->audit_session_id = item->audit.sessionid; + c->audit_login_uid = item->audit.loginuid; + c->mask |= m; + } + break; + + case KDBUS_ITEM_NAMES: + if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { + c->well_known_names_size = item->size - KDBUS_PART_HEADER_SIZE; + c->well_known_names = memdup(item->data, c->well_known_names_size); + if (!c->well_known_names) { + r = -ENOMEM; + goto fail; + } + + c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES; + } + break; + } + } + + if (creds) { + *creds = c; + c = NULL; + } + + r = 0; + +fail: + ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd->offset); + return r; +} + +_public_ int sd_bus_get_owner( + sd_bus *bus, + const char *name, + uint64_t mask, + sd_bus_creds **creds) { + + assert_return(bus, -EINVAL); + assert_return(name, -EINVAL); + assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP); + assert_return(mask == 0 || creds, -EINVAL); + assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); + assert_return(!bus_pid_changed(bus), -ECHILD); + + if (bus->is_kernel) + return bus_get_owner_kdbus(bus, name, mask, creds); + else + return bus_get_owner_dbus(bus, name, mask, creds); } static int add_name_change_match(sd_bus *bus, @@ -578,192 +793,6 @@ static int add_name_change_match(sd_bus *bus, return 0; } -static int kdbus_name_info( - sd_bus *bus, - const char *name, - uint64_t mask, - char **owner, - sd_bus_creds **creds) { - - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; - _cleanup_free_ struct kdbus_cmd_name_info *cmd = NULL; - _cleanup_free_ char *unique = NULL; - struct kdbus_name_info *name_info; - struct kdbus_item *item; - uint64_t attach_flags, m; - size_t size; - int r; - - r = kdbus_translate_attach_flags(mask, &attach_flags); - if (r < 0) - return r; - - size = sizeof(struct kdbus_cmd_name_info) + strlen(name) + 1; - cmd = malloc0(size); - if (!cmd) - return -ENOMEM; - - cmd ->size = size; - cmd->attach_flags = attach_flags; - strcpy(cmd->name, name); - - r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_NAME_INFO, cmd); - if (r < 0) - return -errno; - - name_info = (struct kdbus_name_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset); - - asprintf(&unique, ":1.%llu", (unsigned long long) name_info->id); - - c = bus_creds_new(); - if (!c) - return -ENOMEM; - - KDBUS_PART_FOREACH(item, name_info, items) { - switch (item->type) { - case KDBUS_ITEM_CREDS: - m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID | - SD_BUS_CREDS_TID | SD_BUS_CREDS_PID_STARTTIME) & mask; - - if (m) { - c->uid = item->creds.uid; - c->pid = item->creds.pid; - c->gid = item->creds.gid; - c->tid = item->creds.tid; - c->pid_starttime = item->creds.starttime; - c->mask |= m; - } - break; - - case KDBUS_ITEM_PID_COMM: - if (mask & SD_BUS_CREDS_COMM) { - c->comm = strdup(item->str); - if (!c->comm) - return -ENOMEM; - - c->mask |= SD_BUS_CREDS_COMM; - } - break; - - case KDBUS_ITEM_TID_COMM: - if (mask & SD_BUS_CREDS_TID_COMM) { - c->tid_comm = strdup(item->str); - if (!c->tid_comm) - return -ENOMEM; - - c->mask |= SD_BUS_CREDS_TID_COMM; - } - break; - - case KDBUS_ITEM_EXE: - if (mask & SD_BUS_CREDS_EXE) { - c->exe = strdup(item->str); - if (!c->exe) - return -ENOMEM; - - c->mask |= SD_BUS_CREDS_EXE; - } - break; - - case KDBUS_ITEM_CMDLINE: - if (mask & SD_BUS_CREDS_CMDLINE) { - c->cmdline_length = item->size - KDBUS_PART_HEADER_SIZE; - c->cmdline = memdup(item->data, c->cmdline_length); - if (!c->cmdline) - return -ENOMEM; - - c->mask |= SD_BUS_CREDS_CMDLINE; - } - break; - - case KDBUS_ITEM_CGROUP: - m = (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) & mask; - - if (m) { - c->cgroup = strdup(item->str); - if (!c->cgroup) - return -ENOMEM; - - c->mask |= m; - } - break; - - case KDBUS_ITEM_CAPS: - m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS | - SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask; - - if (m) { - c->capability_size = item->size - KDBUS_PART_HEADER_SIZE; - c->capability = memdup(item->data, c->capability_size); - if (!c->capability) - return -ENOMEM; - - c->mask |= m; - } - break; - - case KDBUS_ITEM_SECLABEL: - if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) { - c->label = strdup(item->str); - if (!c->label) - return -ENOMEM; - - c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT; - } - break; - - case KDBUS_ITEM_AUDIT: - m = (SD_BUS_CREDS_AUDIT_SESSION_ID | SD_BUS_CREDS_AUDIT_LOGIN_UID) & mask; - - if (m) { - c->audit_session_id = item->audit.sessionid; - c->audit_login_uid = item->audit.loginuid; - c->mask |= m; - } - break; - } - } - - r = ioctl(sd_bus_get_fd(bus), KDBUS_CMD_FREE, &cmd->offset); - if (r < 0) - return -errno; - - if (creds) { - *creds = c; - c = NULL; - } - - if (owner) { - *owner = unique; - unique = NULL; - } - - return 0; -} - -_public_ int sd_bus_get_owner( - sd_bus *bus, - const char *name, - uint64_t mask, - char **owner, - sd_bus_creds **creds) { - - assert_return(bus, -EINVAL); - assert_return(name, -EINVAL); - assert_return(mask <= _SD_BUS_CREDS_MAX, -ENOTSUP); - assert_return(mask == 0 || creds, -EINVAL); - assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); - assert_return(!bus_pid_changed(bus), -ECHILD); - - if (bus->is_kernel) - return kdbus_name_info(bus, name, mask, owner, creds); - - return sd_bus_get_owner_dbus(bus, name, mask, owner, creds); -} - int bus_add_match_internal( sd_bus *bus, const char *match, diff --git a/src/libsystemd-bus/bus-convenience.c b/src/libsystemd-bus/bus-convenience.c index 1a9c51fdc..d4c1929ff 100644 --- a/src/libsystemd-bus/bus-convenience.c +++ b/src/libsystemd-bus/bus-convenience.c @@ -433,10 +433,10 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b * to get it from the sender or peer */ if (call->sender) - return sd_bus_get_owner(call->bus, call->sender, mask, NULL, creds); + return sd_bus_get_owner(call->bus, call->sender, mask, creds); else return sd_bus_get_peer_creds(call->bus, mask, creds); } - return sd_bus_creds_extend(c, mask, creds); + return bus_creds_extend_by_pid(c, mask, creds); } diff --git a/src/libsystemd-bus/bus-creds.c b/src/libsystemd-bus/bus-creds.c index eee108b0b..54dcd41b1 100644 --- a/src/libsystemd-bus/bus-creds.c +++ b/src/libsystemd-bus/bus-creds.c @@ -28,6 +28,7 @@ #include "bus-message.h" #include "bus-util.h" #include "time-util.h" +#include "strv.h" #include "bus-creds.h" enum { @@ -48,7 +49,8 @@ void bus_creds_done(sd_bus_creds *c) { free(c->user_unit); free(c->slice); - free(c->cmdline_array); + strv_free(c->cmdline_array); + strv_free(c->well_known_names_array); } _public_ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c) { @@ -86,6 +88,8 @@ _public_ sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c) { free(c->cgroup); free(c->capability); free(c->label); + free(c->unique_name); + free(c->well_known_names); free(c); } } else { @@ -333,34 +337,19 @@ _public_ int sd_bus_creds_get_owner_uid(sd_bus_creds *c, uid_t *uid) { } _public_ int sd_bus_creds_get_cmdline(sd_bus_creds *c, char ***cmdline) { - size_t n, i; - const char *p; - bool first; - assert_return(c, -EINVAL); assert_return(c->cmdline, -ESRCH); assert_return(c->mask & SD_BUS_CREDS_CMDLINE, -ENODATA); assert(c->cmdline); - for (p = c->cmdline, n = 0; p < c->cmdline + c->cmdline_length; p++) - if (*p == 0) - n++; - - *(char***) &c->cmdline_array = new(char*, n + 1); - if (!c->cmdline_array) - return -ENOMEM; - - for (p = c->cmdline, i = 0, first = true; p < c->cmdline + c->cmdline_length; p++) { - if (first) - c->cmdline_array[i++] = (char*) p; - - first = *p == 0; + if (!c->cmdline_array) { + c->cmdline_array = strv_parse_nulstr(c->cmdline, c->cmdline_size); + if (!c->cmdline_array) + return -ENOMEM; } - c->cmdline_array[i] = NULL; *cmdline = c->cmdline_array; - return 0; } @@ -382,6 +371,32 @@ _public_ int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *uid) { return 0; } +_public_ int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **unique_name) { + assert_return(c, -EINVAL); + assert_return(unique_name, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_UNIQUE_NAME, -ENODATA); + + *unique_name = c->unique_name; + return 0; +} + +_public_ int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***well_known_names) { + assert_return(c, -EINVAL); + assert_return(well_known_names, -EINVAL); + assert_return(c->mask & SD_BUS_CREDS_WELL_KNOWN_NAMES, -ENODATA); + + assert(c->well_known_names); + + if (!c->well_known_names_array) { + c->well_known_names_array = strv_parse_nulstr(c->well_known_names, c->well_known_names_size); + if (!c->well_known_names_array) + return -ENOMEM; + } + + *well_known_names = c->well_known_names_array; + return 0; +} + static int has_cap(sd_bus_creds *c, unsigned offset, int capability) { size_t sz; @@ -625,11 +640,11 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { const char *p; p = procfs_file_alloca(pid, "cmdline"); - r = read_full_file(p, &c->cmdline, &c->cmdline_length); + r = read_full_file(p, &c->cmdline, &c->cmdline_size); if (r < 0) return r; - if (c->cmdline_length == 0) { + if (c->cmdline_size == 0) { free(c->cmdline); c->cmdline = NULL; } else @@ -677,12 +692,12 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { return 0; } -_public_ int sd_bus_creds_extend(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) { +int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret) { _cleanup_bus_creds_unref_ sd_bus_creds *n = NULL; int r; - assert_return(c, -EINVAL); - assert_return(ret, -EINVAL); + assert(c); + assert(ret); if ((mask & ~c->mask) == 0) { /* There's already all data we need. */ @@ -747,11 +762,11 @@ _public_ int sd_bus_creds_extend(sd_bus_creds *c, uint64_t mask, sd_bus_creds ** } if (c->mask & mask & SD_BUS_CREDS_CMDLINE) { - n->cmdline = memdup(c->cmdline, c->cmdline_length); + n->cmdline = memdup(c->cmdline, c->cmdline_size); if (!n->cmdline) return -ENOMEM; - n->cmdline_length = c->cmdline_length; + n->cmdline_size = c->cmdline_size; n->mask |= SD_BUS_CREDS_CMDLINE; } @@ -782,6 +797,20 @@ _public_ int sd_bus_creds_extend(sd_bus_creds *c, uint64_t mask, sd_bus_creds ** n->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } + if (c->mask & mask & SD_BUS_CREDS_UNIQUE_NAME) { + n->unique_name = strdup(c->unique_name); + if (!n->unique_name) + return -ENOMEM; + } + + if (c->mask & mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) { + n->well_known_names = memdup(c->well_known_names, c->well_known_names_size); + if (!n->well_known_names) + return -ENOMEM; + + n->well_known_names_size = c->well_known_names_size; + } + /* Get more data */ r = bus_creds_add_more(n, mask, diff --git a/src/libsystemd-bus/bus-creds.h b/src/libsystemd-bus/bus-creds.h index e2416aa50..269688a48 100644 --- a/src/libsystemd-bus/bus-creds.h +++ b/src/libsystemd-bus/bus-creds.h @@ -42,7 +42,7 @@ struct sd_bus_creds { char *exe; char *cmdline; - size_t cmdline_length; + size_t cmdline_size; char **cmdline_array; char *cgroup; @@ -58,6 +58,12 @@ struct sd_bus_creds { uid_t audit_login_uid; char *label; + + char *unique_name; + + char *well_known_names; + size_t well_known_names_size; + char **well_known_names_array; }; sd_bus_creds* bus_creds_new(void); @@ -65,3 +71,5 @@ sd_bus_creds* bus_creds_new(void); void bus_creds_done(sd_bus_creds *c); int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid); + +int bus_creds_extend_by_pid(sd_bus_creds *c, uint64_t mask, sd_bus_creds **ret); diff --git a/src/libsystemd-bus/bus-dump.c b/src/libsystemd-bus/bus-dump.c index 9545e181d..849a3200d 100644 --- a/src/libsystemd-bus/bus-dump.c +++ b/src/libsystemd-bus/bus-dump.c @@ -300,7 +300,7 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f) { const char *u = NULL, *uu = NULL, *s = NULL, *sl = NULL; uid_t owner, audit_loginuid; uint32_t audit_sessionid; - char **cmdline = NULL; + char **cmdline = NULL, **well_known = NULL; int r; assert(c); @@ -340,7 +340,7 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f) { if (sd_bus_creds_get_cmdline(c, &cmdline) >= 0) { char **i; - fputs(" CommandLine=", f); + fputs(" CommandLine={", f); STRV_FOREACH(i, cmdline) { if (i != cmdline) fputc(' ', f); @@ -348,7 +348,7 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f) { fputs(*i, f); } - fputs("\n", f); + fputs("}\n", f); } if (c->mask & SD_BUS_CREDS_CGROUP) @@ -381,6 +381,23 @@ int bus_creds_dump(sd_bus_creds *c, FILE *f) { if (audit_loginuid_is_set || audit_sessionid_is_set) fputs("\n", f); + if (c->mask & SD_BUS_CREDS_UNIQUE_NAME) + fprintf(f, " UniqueName=%s", c->unique_name); + + if (sd_bus_creds_get_well_known_names(c, &well_known) >= 0) { + char **i; + + fputs(" WellKnownNames={", f); + STRV_FOREACH(i, well_known) { + if (i != well_known) + fputc(' ', f); + + fputs(*i, f); + } + + fputs("}\n", f); + } + dump_capabilities(c, f, "EffectiveCapabilities", sd_bus_creds_has_effective_cap); dump_capabilities(c, f, "PermittedCapabilities", sd_bus_creds_has_permitted_cap); dump_capabilities(c, f, "InheritableCapabilities", sd_bus_creds_has_inheritable_cap); diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index b63fe56c4..51e882c73 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -775,7 +775,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { case KDBUS_ITEM_CMDLINE: m->creds.cmdline = d->str; - m->creds.cmdline_length = l; + m->creds.cmdline_size = l; m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask; break; @@ -800,9 +800,14 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { destination = d->str; break; + case KDBUS_ITEM_NAMES: + m->creds.well_known_names = d->str; + m->creds.well_known_names_size = l; + m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask; + break; + case KDBUS_ITEM_FDS: case KDBUS_ITEM_SECLABEL: - case KDBUS_ITEM_NAMES: break; default: @@ -818,7 +823,8 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { m->sender = "org.freedesktop.DBus"; else { snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id); - m->sender = m->sender_buffer; + m->sender = m->creds.unique_name = m->sender_buffer; + m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & bus->creds_mask; } if (!m->destination) { @@ -1029,6 +1035,9 @@ int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) { if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)) m |= KDBUS_ATTACH_AUDIT; + if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) + m |= KDBUS_ATTACH_NAMES; + *kdbus_mask = m; return 0; } diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 56bf88c39..639b9a621 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -3826,6 +3826,12 @@ int bus_message_parse_fields(sd_bus_message *m) { return -EBADMSG; r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender); + + if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) { + m->creds.unique_name = (char*) m->sender; + m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask; + } + break; diff --git a/src/libsystemd-bus/busctl.c b/src/libsystemd-bus/busctl.c index 7649be29f..f557e5003 100644 --- a/src/libsystemd-bus/busctl.c +++ b/src/libsystemd-bus/busctl.c @@ -82,7 +82,6 @@ static int list_bus_names(sd_bus *bus, char **argv) { STRV_FOREACH(i, l) { _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - _cleanup_free_ char *owner = NULL; sd_id128_t mid; if (arg_no_unique && (*i)[0] == ':') @@ -94,8 +93,9 @@ static int list_bus_names(sd_bus *bus, char **argv) { printf("%-*s", (int) max_i, *i); - r = sd_bus_get_owner(bus, *i, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM, &owner, &creds); + r = sd_bus_get_owner(bus, *i, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_COMM|SD_BUS_CREDS_UNIQUE_NAME, &creds); if (r >= 0) { + const char *unique; pid_t pid; uid_t uid; @@ -124,8 +124,9 @@ static int list_bus_names(sd_bus *bus, char **argv) { } else fputs(" - ", stdout); - if (owner) - printf(" %-20s", owner); + r = sd_bus_creds_get_unique_name(creds, &unique); + if (r >= 0) + printf(" %-20s", unique); else fputs(" - ", stdout); diff --git a/src/libsystemd-bus/libsystemd-bus.sym b/src/libsystemd-bus/libsystemd-bus.sym index 054bc3ff0..389efc327 100644 --- a/src/libsystemd-bus/libsystemd-bus.sym +++ b/src/libsystemd-bus/libsystemd-bus.sym @@ -157,7 +157,6 @@ global: sd_bus_creds_new_from_pid; sd_bus_creds_ref; sd_bus_creds_unref; - sd_bus_creds_extend; sd_bus_creds_get_mask; sd_bus_creds_get_uid; sd_bus_creds_get_gid; @@ -181,6 +180,8 @@ global: sd_bus_creds_get_selinux_context; sd_bus_creds_get_audit_session_id; sd_bus_creds_get_audit_login_uid; + sd_bus_creds_get_unique_name; + sd_bus_creds_get_well_known_names; /* Error structures */ sd_bus_error_free; diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 37b6fedf0..4bbeea92f 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -290,6 +290,9 @@ _public_ int sd_bus_negotiate_attach_creds(sd_bus *bus, uint64_t mask) { assert_return(bus->state == BUS_UNSET, -EPERM); assert_return(!bus_pid_changed(bus), -ECHILD); + /* The well knowns we need unconditionally, so that matches can work */ + mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES; + return kdbus_translate_attach_flags(mask, &bus->creds_mask); } diff --git a/src/shared/strv.c b/src/shared/strv.c index adeee282b..607c221ae 100644 --- a/src/shared/strv.c +++ b/src/shared/strv.c @@ -531,7 +531,7 @@ char **strv_parse_nulstr(const char *s, size_t l) { assert(s || l <= 0); if (l <= 0) - return strv_new(NULL, NULL); + return new0(char*, 1); for (p = s; p < s + l; p++) if (*p == 0) diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 1a269f53b..648b955cf 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -48,11 +48,11 @@ typedef struct { /* Flags */ enum { - SD_BUS_CREDS_UID = 1ULL << 0, - SD_BUS_CREDS_GID = 1ULL << 1, - SD_BUS_CREDS_PID = 1ULL << 2, - SD_BUS_CREDS_PID_STARTTIME = 1ULL << 3, - SD_BUS_CREDS_TID = 1ULL << 4, + SD_BUS_CREDS_PID = 1ULL << 0, + 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, @@ -70,7 +70,9 @@ enum { 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_MAX = (1ULL << 22) -1, + SD_BUS_CREDS_UNIQUE_NAME = 1ULL << 22, + SD_BUS_CREDS_WELL_KNOWN_NAMES = 1ULL << 23, + _SD_BUS_CREDS_MAX = (1ULL << 24) -1, }; /* Callbacks */ @@ -233,8 +235,8 @@ int sd_bus_message_rewind(sd_bus_message *m, int complete); int sd_bus_get_unique_name(sd_bus *bus, const char **unique); int sd_bus_request_name(sd_bus *bus, const char *name, int flags); int sd_bus_release_name(sd_bus *bus, const char *name); -int sd_bus_list_names(sd_bus *bus, char ***l); -int sd_bus_get_owner(sd_bus *bus, const char *name, uint64_t mask, char **owner, sd_bus_creds **creds); /* free/unref the result! */ +int sd_bus_list_names(sd_bus *bus, char ***l); /* free the results */ +int sd_bus_get_owner(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **creds); /* unref the result! */ int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine); /* Convenience calls */ @@ -271,13 +273,11 @@ sd_bus_creds *sd_bus_creds_ref(sd_bus_creds *c); sd_bus_creds *sd_bus_creds_unref(sd_bus_creds *c); uint64_t sd_bus_creds_get_mask(sd_bus_creds *c); -int sd_bus_creds_extend(sd_bus_creds *c, uint64_t creds_mask, sd_bus_creds **ret); /* unref the result */ - -int sd_bus_creds_get_uid(sd_bus_creds *c, uid_t *uid); -int sd_bus_creds_get_gid(sd_bus_creds *c, gid_t *gid); 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_gid(sd_bus_creds *c, gid_t *gid); int sd_bus_creds_get_comm(sd_bus_creds *c, const char **r); int sd_bus_creds_get_tid_comm(sd_bus_creds *c, const char **r); int sd_bus_creds_get_exe(sd_bus_creds *c, const char **r); @@ -295,6 +295,8 @@ int sd_bus_creds_has_bounding_cap(sd_bus_creds *c, int capability); int sd_bus_creds_get_selinux_context(sd_bus_creds *c, const char **r); int sd_bus_creds_get_audit_session_id(sd_bus_creds *c, uint32_t *sessionid); int sd_bus_creds_get_audit_login_uid(sd_bus_creds *c, uid_t *loginuid); +int sd_bus_creds_get_unique_name(sd_bus_creds *c, const char **name); +int sd_bus_creds_get_well_known_names(sd_bus_creds *c, char ***names); /* Error structures */ -- 2.30.2