X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-control.c;h=e7e9ba07b0a4f5bab1681f1036624cf9ee5415f0;hb=843f737ade9c73609a2280dd3dd16e18222a5dcb;hp=333968aee4a6a46401a6f86b4e46f73cabccd77e;hpb=5a884f93fdb2a6f89605e44a0e7f4d2db5470b5b;p=elogind.git diff --git a/src/libsystemd-bus/bus-control.c b/src/libsystemd-bus/bus-control.c index 333968aee..e7e9ba07b 100644 --- a/src/libsystemd-bus/bus-control.c +++ b/src/libsystemd-bus/bus-control.c @@ -33,6 +33,7 @@ #include "bus-control.h" #include "bus-bloom.h" #include "bus-util.h" +#include "cgroup-util.h" _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { int r; @@ -96,7 +97,7 @@ static int bus_request_name_dbus1(sd_bus *bus, const char *name, uint64_t flags) r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "RequestName", NULL, @@ -173,7 +174,7 @@ static int bus_release_name_dbus1(sd_bus *bus, const char *name) { r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "ReleaseName", NULL, @@ -230,10 +231,10 @@ static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) { KDBUS_ITEM_FOREACH(name, name_list, names) { - if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->id != previous_id) { + if ((flags & KDBUS_NAME_LIST_UNIQUE) && name->owner_id != previous_id) { char *n; - if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) + if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) return -ENOMEM; r = strv_push(x, n); @@ -242,7 +243,7 @@ static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) { return -ENOMEM; } - previous_id = name->id; + previous_id = name->owner_id; } if (name->size > sizeof(*name) && service_name_is_valid(name->name)) { @@ -295,7 +296,7 @@ static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatab r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames", NULL, @@ -315,7 +316,7 @@ static int bus_list_names_dbus1(sd_bus *bus, char ***acquired, char ***activatab r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListActivatableNames", NULL, @@ -387,6 +388,10 @@ static int bus_get_owner_kdbus( conn_info = (struct kdbus_conn_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset); + /* Non-activated names are considered not available */ + if (conn_info->flags & KDBUS_HELLO_ACTIVATOR) + return name[0] == ':' ? -ENXIO : -ENOENT; + c = bus_creds_new(); if (!c) return -ENOMEM; @@ -403,17 +408,25 @@ static int bus_get_owner_kdbus( 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; + m = (SD_BUS_CREDS_UID | SD_BUS_CREDS_GID | SD_BUS_CREDS_PID) & 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->uid = (uid_t) item->creds.uid; + c->pid = (pid_t) item->creds.pid; + c->gid = (gid_t) item->creds.gid; c->mask |= m; } + + 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_PID_STARTTIME && item->creds.starttime > 0) { + c->pid_starttime = item->creds.starttime; + c->mask |= SD_BUS_CREDS_PID_STARTTIME; + } + break; case KDBUS_ITEM_PID_COMM: @@ -477,6 +490,18 @@ static int bus_get_owner_kdbus( goto fail; } + if (!bus->cgroup_root) { + r = cg_get_root_path(&bus->cgroup_root); + if (r < 0) + goto fail; + } + + c->cgroup_root = strdup(bus->cgroup_root); + if (!c->cgroup_root) { + r = -ENOMEM; + goto fail; + } + c->mask |= m; } break; @@ -561,7 +586,7 @@ static int bus_get_owner_dbus1( r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetNameOwner", NULL, @@ -599,7 +624,7 @@ static int bus_get_owner_dbus1( r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionUnixProcessID", NULL, @@ -628,7 +653,7 @@ static int bus_get_owner_dbus1( r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionUnixUser", NULL, @@ -655,7 +680,7 @@ static int bus_get_owner_dbus1( r = sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext", NULL, @@ -702,6 +727,7 @@ _public_ int sd_bus_get_owner( assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN); assert_return(!bus_pid_changed(bus), -ECHILD); assert_return(service_name_is_valid(name), -EINVAL); + assert_return(bus->bus_client, -ENODATA); if (bus->is_kernel) return bus_get_owner_kdbus(bus, name, mask, creds); @@ -798,7 +824,7 @@ static int add_name_change_match(sd_bus *bus, item->name_change.new.id = new_owner_id; if (name) - strcpy(item->name_change.name, name); + memcpy(item->name_change.name, name, l); /* If the old name is unset or empty, then * this can match against added names */ @@ -820,17 +846,16 @@ static int add_name_change_match(sd_bus *bus, return -errno; } - /* If the neither name is explicitly set to - * the empty string, then this can match - * against changed names */ - if (!(old_owner && old_owner[0] == 0) && - !(new_owner && new_owner[0] == 0)) { - item->type = KDBUS_ITEM_NAME_CHANGE; - - r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); - if (r < 0) - return -errno; - } + /* The CHANGE match we need in either case, because + * what is reported as a name change by the kernel + * might just be an owner change between starter and + * normal clients. For userspace such a change should + * be considered a removal/addition, hence let's + * subscribe to this unconditionally. */ + item->type = KDBUS_ITEM_NAME_CHANGE; + r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); + if (r < 0) + return -errno; } if (is_name_id != 0) { @@ -850,7 +875,9 @@ static int add_name_change_match(sd_bus *bus, m->cookie = cookie; item = m->items; - item->size = offsetof(struct kdbus_item, id_change) + sizeof(struct kdbus_notify_id_change); + item->size = + offsetof(struct kdbus_item, id_change) + + sizeof(struct kdbus_notify_id_change); item->id_change.id = name_id; /* If the old name is unset or empty, then this can @@ -901,8 +928,7 @@ int bus_add_match_internal_kernel( zero(bloom); - sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) + - offsetof(struct kdbus_item, id) + sizeof(uint64_t)); + sz = ALIGN8(offsetof(struct kdbus_cmd_match, items)); for (i = 0; i < n_components; i++) { struct bus_match_component *c = &components[i]; @@ -916,8 +942,9 @@ int bus_add_match_internal_kernel( r = bus_kernel_parse_unique_name(c->value_str, &src_id); if (r < 0) return r; - - if (r > 0) { + else if (r > 0) + sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t)); + else { sender = c->value_str; sender_length = strlen(sender); sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1); @@ -1017,22 +1044,25 @@ int bus_add_match_internal_kernel( m = alloca0(sz); m->size = sz; m->cookie = cookie; - m->id = id; + m->owner_id = id; item = m->items; - item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t); - item->type = KDBUS_ITEM_ID; - item->id = src_id; - if (using_bloom) { + if (src_id != KDBUS_MATCH_ID_ANY) { + item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t); + item->type = KDBUS_ITEM_ID; + item->id = src_id; item = KDBUS_ITEM_NEXT(item); + } + + if (using_bloom) { item->size = offsetof(struct kdbus_item, data64) + BLOOM_SIZE; item->type = KDBUS_ITEM_BLOOM; memcpy(item->data64, bloom, BLOOM_SIZE); + item = KDBUS_ITEM_NEXT(item); } if (sender) { - item = KDBUS_ITEM_NEXT(item); item->size = offsetof(struct kdbus_item, str) + sender_length + 1; item->type = KDBUS_ITEM_NAME; memcpy(item->str, sender, sender_length + 1); @@ -1067,7 +1097,7 @@ static int bus_add_match_internal_dbus1( return sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "AddMatch", NULL, @@ -1105,7 +1135,7 @@ int bus_remove_match_internal_kernel( zero(m); m.size = offsetof(struct kdbus_cmd_match, items); m.cookie = cookie; - m.id = id; + m.owner_id = id; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m); if (r < 0) @@ -1124,7 +1154,7 @@ static int bus_remove_match_internal_dbus1( return sd_bus_call_method( bus, "org.freedesktop.DBus", - "/", + "/org/freedesktop/DBus", "org.freedesktop.DBus", "RemoveMatch", NULL,