X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-kernel.c;h=7c946e61c2481cc81882b3b1c51212b17c8361d7;hb=d29ae2914e1146f45ff4104faafef5331837bed7;hp=d910d8e492e59140a69b0cc020b5355c7d1bd97a;hpb=18ee085c155dcd5f196f2ef9b712698dfd377f82;p=elogind.git diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index d910d8e49..7c946e61c 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -32,6 +32,7 @@ #include "util.h" #include "strv.h" #include "memfd-util.h" +#include "capability.h" #include "cgroup-util.h" #include "fileio.h" @@ -295,7 +296,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { m->kdbus->flags = ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) | - ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0); + ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) | + ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0); if (well_known) /* verify_destination_id will usually be 0, which makes the kernel driver only look @@ -377,15 +379,6 @@ fail: return r; } -static void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m) { - assert(bus); - assert(m); - - m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus"; - m->creds.well_known_names_driver = true; - m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask; -} - static void unset_memfds(struct sd_bus_message *m) { struct bus_body_part *part; unsigned i; @@ -398,6 +391,21 @@ static void unset_memfds(struct sd_bus_message *m) { part->memfd = -1; } +static void message_set_timestamp(sd_bus *bus, sd_bus_message *m, const struct kdbus_timestamp *ts) { + assert(bus); + assert(m); + + if (!ts) + return; + + if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP)) + return; + + m->realtime = ts->realtime_ns / NSEC_PER_USEC; + m->monotonic = ts->monotonic_ns / NSEC_PER_USEC; + m->seqnum = ts->seqnum; +} + static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { sd_bus_message *m = NULL; struct kdbus_item *d; @@ -618,13 +626,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { break; case KDBUS_ITEM_TIMESTAMP: - - if (bus->attach_flags & KDBUS_ATTACH_TIMESTAMP) { - m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC; - m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC; - m->seqnum = d->timestamp.seqnum; - } - + message_set_timestamp(bus, m, &d->timestamp); break; case KDBUS_ITEM_PID_COMM: @@ -673,8 +675,13 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { break; case KDBUS_ITEM_CAPS: - m->creds.capability = (uint8_t *) d->caps.caps; - m->creds.capability_size = d->size - offsetof(struct kdbus_item, caps.caps); + if (d->caps.last_cap != cap_last_cap() || + d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) { + r = -EBADMSG; + goto fail; + } + + m->creds.capability = d->caps.caps; m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask; break; @@ -744,7 +751,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { /* If we requested the list of well-known names to be appended * and the sender had none no item for it will be - * attached. However, this does *not* mean that we the kernel + * attached. However, this does *not* mean that the kernel * didn't want to provide this information to us. Hence, let's * explicitly mark this information as available if it was * requested. */ @@ -1147,7 +1154,13 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call return 1; } -static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) { +static int push_name_owner_changed( + sd_bus *bus, + const char *name, + const char *old_owner, + const char *new_owner, + const struct kdbus_timestamp *ts) { + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; int r; @@ -1167,6 +1180,7 @@ static int push_name_owner_changed(sd_bus *bus, const char *name, const char *ol return r; bus_message_set_sender_driver(bus, m); + message_set_timestamp(bus, m, ts); r = bus_seal_synthetic_message(bus, m); if (r < 0) @@ -1178,7 +1192,12 @@ static int push_name_owner_changed(sd_bus *bus, const char *name, const char *ol return 1; } -static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) { +static int translate_name_change( + sd_bus *bus, + const struct kdbus_msg *k, + const struct kdbus_item *d, + const struct kdbus_timestamp *ts) { + char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX]; assert(bus); @@ -1199,10 +1218,15 @@ static int translate_name_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_ } else sprintf(new_owner, ":1.%llu", (unsigned long long) d->name_change.new_id.id); - return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner); + return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts); } -static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) { +static int translate_id_change( + sd_bus *bus, + const struct kdbus_msg *k, + const struct kdbus_item *d, + const struct kdbus_timestamp *ts) { + char owner[UNIQUE_NAME_MAX]; assert(bus); @@ -1214,10 +1238,16 @@ static int translate_id_change(sd_bus *bus, struct kdbus_msg *k, struct kdbus_it return push_name_owner_changed( bus, owner, d->type == KDBUS_ITEM_ID_ADD ? NULL : owner, - d->type == KDBUS_ITEM_ID_ADD ? owner : NULL); + d->type == KDBUS_ITEM_ID_ADD ? owner : NULL, + ts); } -static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) { +static int translate_reply( + sd_bus *bus, + const struct kdbus_msg *k, + const struct kdbus_item *d, + const struct kdbus_timestamp *ts) { + _cleanup_bus_message_unref_ sd_bus_message *m = NULL; int r; @@ -1235,7 +1265,7 @@ static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item * if (r < 0) return r; - bus_message_set_sender_driver(bus, m); + message_set_timestamp(bus, m, ts); r = bus_seal_synthetic_message(bus, m); if (r < 0) @@ -1248,9 +1278,7 @@ static int translate_reply(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item * } static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { - struct kdbus_item *d, *found = NULL; - - static int (* const translate[])(sd_bus *bus, struct kdbus_msg *k, struct kdbus_item *d) = { + static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = { [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change, [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change, [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change, @@ -1262,11 +1290,17 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply, }; + struct kdbus_item *d, *found = NULL; + struct kdbus_timestamp *ts = NULL; + assert(bus); assert(k); assert(k->payload_type == KDBUS_PAYLOAD_KERNEL); KDBUS_ITEM_FOREACH(d, k, items) { + if (d->type == KDBUS_ITEM_TIMESTAMP) + ts = &d->timestamp; + if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) { if (found) return -EBADMSG; @@ -1280,7 +1314,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { return 0; } - return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found); + return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts); } int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { @@ -1510,6 +1544,7 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { make = alloca0_align(offsetof(struct kdbus_cmd_make, items) + ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) + ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) + + ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) + ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1), 8); @@ -1536,6 +1571,13 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { n->data64[0] = _KDBUS_ATTACH_ANY; make->size += ALIGN8(n->size); + /* Provide all metadata via bus-owner queries */ + n = KDBUS_ITEM_NEXT(n); + n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND; + n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t); + n->data64[0] = _KDBUS_ATTACH_ANY; + make->size += ALIGN8(n->size); + /* Set the a good name */ n = KDBUS_ITEM_NEXT(n); sprintf(n->str, UID_FMT "-%s", getuid(), name); @@ -1565,69 +1607,6 @@ int bus_kernel_create_bus(const char *name, bool world, char **s) { return fd; } -static int bus_kernel_translate_access(BusPolicyAccess access) { - assert(access >= 0); - assert(access < _BUS_POLICY_ACCESS_MAX); - - switch (access) { - - case BUS_POLICY_ACCESS_SEE: - return KDBUS_POLICY_SEE; - - case BUS_POLICY_ACCESS_TALK: - return KDBUS_POLICY_TALK; - - case BUS_POLICY_ACCESS_OWN: - return KDBUS_POLICY_OWN; - - default: - assert_not_reached("Unknown policy access"); - } -} - -static int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) { - int r; - - assert(policy); - assert(item); - - switch (policy->type) { - - case BUSNAME_POLICY_TYPE_USER: { - const char *user = policy->name; - uid_t uid; - - r = get_user_creds(&user, &uid, NULL, NULL, NULL); - if (r < 0) - return r; - - item->policy_access.type = KDBUS_POLICY_ACCESS_USER; - item->policy_access.id = uid; - break; - } - - case BUSNAME_POLICY_TYPE_GROUP: { - const char *group = policy->name; - gid_t gid; - - r = get_group_creds(&group, &gid); - if (r < 0) - return r; - - item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP; - item->policy_access.id = gid; - break; - } - - default: - assert_not_reached("Unknown policy type"); - } - - item->policy_access.access = bus_kernel_translate_access(policy->access); - - return 0; -} - int bus_kernel_open_bus_fd(const char *bus, char **path) { char *p; int fd; @@ -1704,128 +1683,6 @@ int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char * return fd; } -int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) { - - struct kdbus_cmd_update *update; - struct kdbus_item *n; - BusEndpointPolicy *po; - Iterator i; - size_t size; - int r; - - size = ALIGN8(offsetof(struct kdbus_cmd_update, items)); - - HASHMAP_FOREACH(po, ep->policy_hash, i) { - size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1); - size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); - } - - update = alloca0_align(size, 8); - update->size = size; - - n = update->items; - - HASHMAP_FOREACH(po, ep->policy_hash, i) { - n->type = KDBUS_ITEM_NAME; - n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1; - strcpy(n->str, po->name); - n = KDBUS_ITEM_NEXT(n); - - n->type = KDBUS_ITEM_POLICY_ACCESS; - n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); - - n->policy_access.type = KDBUS_POLICY_ACCESS_USER; - n->policy_access.access = bus_kernel_translate_access(po->access); - n->policy_access.id = uid; - - n = KDBUS_ITEM_NEXT(n); - } - - r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update); - if (r < 0) - return -errno; - - return 0; -} - -int bus_kernel_make_starter( - int fd, - const char *name, - bool activating, - bool accept_fd, - BusNamePolicy *policy, - BusPolicyAccess world_policy) { - - struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free) }; - struct kdbus_cmd_hello *hello; - struct kdbus_item *n; - size_t policy_cnt = 0; - BusNamePolicy *po; - size_t size; - int r; - - assert(fd >= 0); - assert(name); - - LIST_FOREACH(policy, po, policy) - policy_cnt++; - - if (world_policy >= 0) - policy_cnt++; - - size = offsetof(struct kdbus_cmd_hello, items) + - ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) + - policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access)); - - hello = alloca0_align(size, 8); - - n = hello->items; - strcpy(n->str, name); - n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1; - n->type = KDBUS_ITEM_NAME; - n = KDBUS_ITEM_NEXT(n); - - LIST_FOREACH(policy, po, policy) { - n->type = KDBUS_ITEM_POLICY_ACCESS; - n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); - - r = bus_kernel_translate_policy(po, n); - if (r < 0) - return r; - - n = KDBUS_ITEM_NEXT(n); - } - - if (world_policy >= 0) { - n->type = KDBUS_ITEM_POLICY_ACCESS; - n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access); - n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD; - n->policy_access.access = bus_kernel_translate_access(world_policy); - } - - hello->size = size; - hello->flags = - (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) | - (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0); - hello->pool_size = KDBUS_POOL_SIZE; - hello->attach_flags_send = _KDBUS_ATTACH_ANY; - hello->attach_flags_recv = _KDBUS_ATTACH_ANY; - - if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) - return -errno; - - /* not interested in any output values */ - cmd_free.offset = hello->offset; - (void) ioctl(fd, KDBUS_CMD_FREE, &cmd_free); - - /* The higher 32bit of the bus_flags fields are considered - * 'incompatible flags'. Refuse them all for now. */ - if (hello->bus_flags > 0xFFFFFFFFULL) - return -ENOTSUP; - - return fd; -} - int bus_kernel_try_close(sd_bus *bus) { assert(bus); assert(bus->is_kernel);