X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-kernel.c;h=cdca48d92baa9cde3b403c042bcce8b7b6a89164;hb=19ee32dc4d337a033c95c7d3302666f2ea4340bd;hp=752c63adb3a1a636726d71ada3bcf9ad2256401a;hpb=cb01aedc3b4ba70859267159fe716253e3551ec6;p=elogind.git diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 752c63adb..cdca48d92 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -294,8 +294,8 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { memzero(m->kdbus, sz); m->kdbus->flags = - ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) | - ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0); + ((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); if (well_known) /* verify_destination_id will usually be 0, which makes the kernel driver only look @@ -761,7 +761,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { } /* Refuse messages where the reply flag doesn't match up */ - if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_FLAGS_EXPECT_REPLY)) { + if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) { r = -EBADMSG; goto fail; } @@ -773,7 +773,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) { } /* Refuse messages where the autostart flag doesn't match up */ - if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_FLAGS_NO_AUTO_START)) { + if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) { r = -EBADMSG; goto fail; } @@ -815,7 +815,13 @@ fail: } int bus_kernel_take_fd(sd_bus *b) { + struct kdbus_cmd_free cmd_free = { + .size = sizeof(cmd_free), + .flags = 0, + }; + 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 +934,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 +980,15 @@ 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: + cmd_free.offset = hello->offset; + (void) ioctl(b->input_fd, KDBUS_CMD_FREE, &cmd_free); + return r; } int bus_kernel_connect(sd_bus *b) { @@ -980,6 +1011,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, }; @@ -1012,6 +1044,7 @@ static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) { } int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) { + struct kdbus_cmd_send cmd = { }; int r; assert(bus); @@ -1027,15 +1060,20 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call if (r < 0) return r; + cmd.size = sizeof(cmd); + cmd.msg_address = (uintptr_t)m->kdbus; + /* If this is a synchronous method call, then let's tell the * kernel, so that it can pass CPU time/scheduling to the * destination for the time, if it wants to. If we * synchronously wait for the result anyway, we won't need CPU * anyway. */ - if (hint_sync_call) - m->kdbus->flags |= KDBUS_MSG_FLAGS_EXPECT_REPLY|KDBUS_MSG_FLAGS_SYNC_REPLY; + if (hint_sync_call) { + m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY; + cmd.flags |= KDBUS_SEND_SYNC_REPLY; + } - r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus); + r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd); if (r < 0) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; sd_bus_message *reply; @@ -1085,7 +1123,7 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call } else if (hint_sync_call) { struct kdbus_msg *k; - k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + m->kdbus->offset_reply); + k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset); assert(k); if (k->payload_type == KDBUS_PAYLOAD_DBUS) { @@ -1246,7 +1284,7 @@ static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) { } int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { - struct kdbus_cmd_recv recv = {}; + struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; struct kdbus_msg *k; int r; @@ -1261,7 +1299,7 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { recv.priority = priority; } - r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, &recv); + r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv); if (r < 0) { if (errno == EAGAIN) return 0; @@ -1274,7 +1312,7 @@ int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) { return -errno; } - k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset); + k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.reply.offset); if (k->payload_type == KDBUS_PAYLOAD_DBUS) { r = bus_kernel_make_message(bus, k); @@ -1472,6 +1510,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); @@ -1498,6 +1537,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); @@ -1718,6 +1764,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; @@ -1775,14 +1822,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; } @@ -1798,12 +1846,13 @@ int bus_kernel_try_close(sd_bus *bus) { int bus_kernel_drop_one(int fd) { struct kdbus_cmd_recv recv = { - .flags = KDBUS_RECV_DROP + .size = sizeof(recv), + .flags = KDBUS_RECV_DROP, }; assert(fd >= 0); - if (ioctl(fd, KDBUS_CMD_MSG_RECV, &recv) < 0) + if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0) return -errno; return 0;