X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibelogind%2Fsd-bus%2Fbus-control.c;h=c29bf30e0b99dc1d082553a31eb5518093472787;hb=94c5f7fa9e34517edad75cd63d71dd459ec4f133;hp=43ddfc651dc273fff596f00d8d9d6fee03031073;hpb=73feab10082362f460519d4c38379ca365f432df;p=elogind.git diff --git a/src/libelogind/sd-bus/bus-control.c b/src/libelogind/sd-bus/bus-control.c index 43ddfc651..c29bf30e0 100644 --- a/src/libelogind/sd-bus/bus-control.c +++ b/src/libelogind/sd-bus/bus-control.c @@ -23,17 +23,22 @@ #include #endif -#include #include +#include -#include "strv.h" #include "sd-bus.h" + +#include "alloc-util.h" +#include "bus-bloom.h" +#include "bus-control.h" #include "bus-internal.h" #include "bus-message.h" -#include "bus-control.h" -#include "bus-bloom.h" #include "bus-util.h" -#include "capability.h" +#include "capability-util.h" +#include "stdio-util.h" +#include "string-util.h" +#include "strv.h" +#include "user-util.h" _public_ int sd_bus_get_unique_name(sd_bus *bus, const char **unique) { int r; @@ -256,11 +261,9 @@ static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) { name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset); KDBUS_FOREACH(name, name_list, cmd.list_size) { - struct kdbus_item *item; - const char *entry_name = NULL; - if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id) { + if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) { char *n; if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) { @@ -275,15 +278,15 @@ static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) { previous_id = name->id; } - KDBUS_ITEM_FOREACH(item, name, items) - if (item->type == KDBUS_ITEM_OWNED_NAME) - entry_name = item->name.name; - - if (entry_name && service_name_is_valid(entry_name)) { - r = strv_extend(x, entry_name); - if (r < 0) { - r = -ENOMEM; - goto fail; + KDBUS_ITEM_FOREACH(item, name, items) { + if (item->type == KDBUS_ITEM_OWNED_NAME) { + if (service_name_is_valid(item->name.name)) { + r = strv_extend(x, item->name.name); + if (r < 0) { + r = -ENOMEM; + goto fail; + } + } } } } @@ -978,9 +981,15 @@ static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds ** static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) { _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; pid_t pid = 0; + bool do_label; int r; - if (!bus->ucred_valid && !isempty(bus->label)) + assert(bus); + + do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT); + + /* Avoid allocating anything if we have no chance of returning useful data */ + if (!bus->ucred_valid && !do_label) return -ENODATA; c = bus_creds_new(); @@ -1004,7 +1013,7 @@ static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds ** } } - if (!isempty(bus->label) && (mask & SD_BUS_CREDS_SELINUX_CONTEXT)) { + if (do_label) { c->label = strdup(bus->label); if (!c->label) return -ENOMEM; @@ -1129,7 +1138,7 @@ static int add_name_change_match(sd_bus *bus, /* If the old name is unset or empty, then * this can match against added names */ - if (!old_owner || old_owner[0] == 0) { + if (isempty(old_owner)) { item->type = KDBUS_ITEM_NAME_ADD; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); @@ -1139,7 +1148,7 @@ static int add_name_change_match(sd_bus *bus, /* If the new name is unset or empty, then * this can match against removed names */ - if (!new_owner || new_owner[0] == 0) { + if (isempty(new_owner)) { item->type = KDBUS_ITEM_NAME_REMOVE; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); @@ -1183,8 +1192,10 @@ static int add_name_change_match(sd_bus *bus, /* If the old name is unset or empty, then this can * match against added ids */ - if (!old_owner || old_owner[0] == 0) { + if (isempty(old_owner)) { item->type = KDBUS_ITEM_ID_ADD; + if (!isempty(new_owner)) + item->id_change.id = new_owner_id; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) @@ -1193,8 +1204,10 @@ static int add_name_change_match(sd_bus *bus, /* If thew new name is unset or empty, then this can * match against removed ids */ - if (!new_owner || new_owner[0] == 0) { + if (isempty(new_owner)) { item->type = KDBUS_ITEM_ID_REMOVE; + if (!isempty(old_owner)) + item->id_change.id = old_owner_id; r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m); if (r < 0) @@ -1217,7 +1230,7 @@ int bus_add_match_internal_kernel( size_t sz; const char *sender = NULL; size_t sender_length = 0; - uint64_t src_id = KDBUS_MATCH_ID_ANY; + uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY; bool using_bloom = false; unsigned i; bool matches_name_change = true; @@ -1289,10 +1302,8 @@ int bus_add_match_internal_kernel( break; case BUS_MATCH_PATH_NAMESPACE: - if (!streq(c->value_str, "/")) { - bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str); - using_bloom = true; - } + bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str); + using_bloom = true; break; case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: { @@ -1307,15 +1318,30 @@ int bus_add_match_internal_kernel( break; } - case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: { - char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")]; + case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: { + char buf[sizeof("arg")-1 + 2 + sizeof("-has")]; - xsprintf(buf, "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH); + xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS); bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str); using_bloom = true; break; } + case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: + /* + * XXX: DBus spec defines arg[0..63]path= matching to be + * a two-way glob. That is, if either string is a prefix + * of the other, it matches. + * This is really hard to realize in bloom-filters, as + * we would have to create a bloom-match for each prefix + * of @c->value_str. This is excessive, hence we just + * ignore all those matches and accept everything from + * the kernel. People should really avoid those matches. + * If they're used in real-life some day, we will have + * to properly support multiple-matches here. + */ + break; + case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: { char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")]; @@ -1326,11 +1352,22 @@ int bus_add_match_internal_kernel( } case BUS_MATCH_DESTINATION: - /* The bloom filter does not include - the destination, since it is only - available for broadcast messages - which do not carry a destination - since they are undirected. */ + /* + * Kernel only supports matching on destination IDs, but + * not on destination names. So just skip the + * destination name restriction and verify it in + * user-space on retrieval. + */ + r = bus_kernel_parse_unique_name(c->value_str, &dst_id); + if (r < 0) + return r; + else if (r > 0) + sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t)); + + /* if not a broadcast, it cannot be a name-change */ + if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST) + matches_name_change = false; + break; case BUS_MATCH_ROOT: @@ -1358,6 +1395,13 @@ int bus_add_match_internal_kernel( item = KDBUS_ITEM_NEXT(item); } + if (dst_id != KDBUS_MATCH_ID_ANY) { + item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t); + item->type = KDBUS_ITEM_DST_ID; + item->id = dst_id; + item = KDBUS_ITEM_NEXT(item); + } + if (using_bloom) { item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size; item->type = KDBUS_ITEM_BLOOM_MASK; @@ -1498,6 +1542,8 @@ int bus_remove_match_internal( return bus_remove_match_internal_dbus1(bus, match); } +/// UNNEEDED by elogind +#if 0 _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL, *m = NULL; const char *mid; @@ -1542,3 +1588,4 @@ _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_ return sd_id128_from_string(mid, machine); } +#endif // 0