diff options
Diffstat (limited to 'src/libsystemd')
-rw-r--r-- | src/libsystemd/sd-bus/bus-kernel.c | 53 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/bus-message.c | 1 | ||||
-rw-r--r-- | src/libsystemd/sd-bus/kdbus.h | 21 |
3 files changed, 62 insertions, 13 deletions
diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 2978b0a284..112292735b 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -815,7 +815,9 @@ fail: } int bus_kernel_take_fd(sd_bus *b) { + struct kdbus_bloom_parameter *bloom = NULL; struct kdbus_cmd_hello *hello; + struct kdbus_item_list *items; struct kdbus_item *item; _cleanup_free_ char *g = NULL; const char *name; @@ -928,23 +930,40 @@ int bus_kernel_take_fd(sd_bus *b) { b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0); if (b->kdbus_buffer == MAP_FAILED) { b->kdbus_buffer = NULL; - return -errno; + r = -errno; + goto fail; } } /* The higher 32bit of the bus_flags fields are considered * 'incompatible flags'. Refuse them all for now. */ - if (hello->bus_flags > 0xFFFFFFFFULL) - return -ENOTSUP; + if (hello->bus_flags > 0xFFFFFFFFULL) { + r = -ENOTSUP; + goto fail; + } - if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash)) - return -ENOTSUP; + /* extract bloom parameters from items */ + items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset); + KDBUS_ITEM_FOREACH(item, items, items) { + switch (item->type) { + case KDBUS_ITEM_BLOOM_PARAMETER: + bloom = &item->bloom_parameter; + break; + } + } - b->bloom_size = (size_t) hello->bloom.size; - b->bloom_n_hash = (unsigned) hello->bloom.n_hash; + if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) { + r = -ENOTSUP; + goto fail; + } - if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) - return -ENOMEM; + b->bloom_size = (size_t) bloom->size; + b->bloom_n_hash = (unsigned) bloom->n_hash; + + if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0) { + r = -ENOMEM; + goto fail; + } b->unique_id = hello->id; @@ -957,7 +976,14 @@ int bus_kernel_take_fd(sd_bus *b) { /* the kernel told us the UUID of the underlying bus */ memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes)); + /* free returned items */ + (void) bus_kernel_cmd_free(b, hello->offset); + return bus_start_running(b); + +fail: + (void) bus_kernel_cmd_free(b, hello->offset); + return r; } int bus_kernel_connect(sd_bus *b) { @@ -980,6 +1006,7 @@ int bus_kernel_connect(sd_bus *b) { int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) { struct kdbus_cmd_free cmd = { + .size = sizeof(cmd), .flags = 0, .offset = offset, }; @@ -1724,6 +1751,7 @@ int bus_kernel_make_starter( 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; @@ -1781,14 +1809,15 @@ int bus_kernel_make_starter( 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; - if (!bloom_validate_parameters((size_t) hello->bloom.size, (unsigned) hello->bloom.n_hash)) - return -ENOTSUP; - return fd; } diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 3134029337..0f9334bb84 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -132,6 +132,7 @@ static void message_free(sd_bus_message *m) { if (m->release_kdbus) { struct kdbus_cmd_free cmd_free = { }; + cmd_free.size = sizeof(cmd_free); cmd_free.flags = 0; cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer; (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free); diff --git a/src/libsystemd/sd-bus/kdbus.h b/src/libsystemd/sd-bus/kdbus.h index bd51e37593..201f21dd13 100644 --- a/src/libsystemd/sd-bus/kdbus.h +++ b/src/libsystemd/sd-bus/kdbus.h @@ -384,6 +384,16 @@ struct kdbus_item { }; /** + * struct kdbus_item_list - A list of items + * @size: The total size of the structure + * @items: Array of items + */ +struct kdbus_item_list { + __u64 size; + struct kdbus_item items[0]; +}; + +/** * enum kdbus_msg_flags - type of message * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for * method calls. The userspace-supplied @@ -576,19 +586,23 @@ struct kdbus_cmd_cancel { /** * struct kdbus_cmd_free - struct to free a slice of memory in the pool + * @size: Overall size of this structure * @offset: The offset of the memory slice, as returned by other * ioctls * @flags: Flags for the free command, userspace → kernel * @return_flags: Command return flags, kernel → userspace * @kernel_flags: Supported flags of the free command, userspace → kernel + * @items: Additional items to modify the behavior * * This struct is used with the KDBUS_CMD_FREE ioctl. */ struct kdbus_cmd_free { + __u64 size; __u64 offset; __u64 flags; __u64 kernel_flags; __u64 return_flags; + struct kdbus_item items[0]; } __attribute__((aligned(8))); /** @@ -701,6 +715,10 @@ enum kdbus_attach_flags { * @id: The ID of this connection (kernel → userspace) * @pool_size: Size of the connection's buffer where the received * messages are placed + * @offset: Pool offset where additional items of type + * kdbus_item_list are stored. They contain information + * about the bus and the newly created connection. + * @items_size: Copy of item_list.size stored in @offset. * @bloom: The bloom properties of the bus, specified * by the bus creator (kernel → userspace) * @id128: Unique 128-bit ID of the bus (kernel → userspace) @@ -718,7 +736,8 @@ struct kdbus_cmd_hello { __u64 bus_flags; __u64 id; __u64 pool_size; - struct kdbus_bloom_parameter bloom; + __u64 offset; + __u64 items_size; __u8 id128[16]; struct kdbus_item items[0]; } __attribute__((aligned(8))); |