}
int bus_kernel_take_fd(sd_bus *b) {
- struct kdbus_cmd_hello hello;
+ struct kdbus_cmd_hello *hello;
+ struct kdbus_item *item;
+ size_t l, sz;
int r;
assert(b);
b->use_memfd = 1;
- zero(hello);
- hello.size = sizeof(hello);
- hello.conn_flags = b->hello_flags;
- hello.attach_flags = b->attach_flags;
- hello.pool_size = KDBUS_POOL_SIZE;
+ sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items));
+
+ if (b->fake_creds_valid)
+ sz += ALIGN8(offsetof(struct kdbus_item, creds));
+
+ if (b->fake_label) {
+ l = strlen(b->fake_label);
+ sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
+ }
+
+ hello = alloca0(sz);
+ hello->size = sz;
+ hello->conn_flags = b->hello_flags;
+ hello->attach_flags = b->attach_flags;
+ hello->pool_size = KDBUS_POOL_SIZE;
+
+ item = hello->items;
+
+ if (b->fake_creds_valid) {
+ item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
+ item->type = KDBUS_ITEM_CREDS;
+ item->creds = b->fake_creds;
+
+ item = KDBUS_ITEM_NEXT(item);
+ }
+
+ if (b->fake_label) {
+ item->size = offsetof(struct kdbus_item, str) + l + 1;
+ memcpy(item->str, b->fake_label, l+1);
+ }
- r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello);
+ r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
if (r < 0)
return -errno;
/* The higher 32bit of both flags fields are considered
* 'incompatible flags'. Refuse them all for now. */
- if (hello.bus_flags > 0xFFFFFFFFULL ||
- hello.conn_flags > 0xFFFFFFFFULL)
+ if (hello->bus_flags > 0xFFFFFFFFULL ||
+ hello->conn_flags > 0xFFFFFFFFULL)
return -ENOTSUP;
- if (hello.bloom_size != BLOOM_SIZE)
+ if (hello->bloom_size != BLOOM_SIZE)
return -ENOTSUP;
- if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0)
+ if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello->id) < 0)
return -ENOMEM;
- b->unique_id = hello.id;
+ b->unique_id = hello->id;
b->is_kernel = true;
b->bus_client = true;
- b->can_fds = !!(hello.conn_flags & KDBUS_HELLO_ACCEPT_FD);
+ b->can_fds = !!(hello->conn_flags & KDBUS_HELLO_ACCEPT_FD);
b->message_version = 2;
b->message_endian = BUS_NATIVE_ENDIAN;
/* the kernel told us the UUID of the underlying bus */
- memcpy(b->server_id.bytes, hello.id128, sizeof(b->server_id.bytes));
+ memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
return bus_start_running(b);
}
case KDBUS_ITEM_PAYLOAD_OFF:
if (!h) {
- h = (struct bus_header *)((uint8_t *)bus->kdbus_buffer + d->vec.offset);
+ h = (struct bus_header *)((uint8_t *)k + d->vec.offset);
if (!bus_header_is_complete(h, d->vec.size))
return -EBADMSG;
if (r < 0)
return r;
+ /* The well-known names list is different from the other
+ credentials. If we asked for it, but nothing is there, this
+ means that the list of well-known names is simply empty, not
+ that we lack any data */
+
+ m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
+
KDBUS_ITEM_FOREACH(d, k, items) {
size_t l;
if (idx >= begin_body) {
if (!part->is_zero)
- part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset;
+ part->data = (uint8_t *)k + d->vec.offset;
part->size = d->vec.size;
} else {
if (!part->is_zero)
- part->data = (uint8_t *)bus->kdbus_buffer + d->vec.offset + (begin_body - idx);
+ part->data = (uint8_t *)k + d->vec.offset + (begin_body - idx);
part->size = d->vec.size - (begin_body - idx);
}
r = strv_extend(&m->creds.well_known_names, d->name.name);
if (r < 0)
goto fail;
- m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES & bus->creds_mask;
break;
case KDBUS_ITEM_FDS:
/* Override information from the user header with data from the kernel */
if (k->src_id == KDBUS_SRC_ID_KERNEL)
- m->sender = "org.freedesktop.DBus";
+ m->sender = m->creds.unique_name = (char*) "org.freedesktop.DBus";
else {
snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id);
m->sender = m->creds.unique_name = m->sender_buffer;
- m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & bus->creds_mask;
}
- if (!m->destination) {
- if (destination)
- m->destination = destination;
- else if (k->dst_id != KDBUS_DST_ID_NAME &&
- k->dst_id != KDBUS_DST_ID_BROADCAST) {
- snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
- m->destination = m->destination_buffer;
- }
+ if (destination)
+ m->destination = destination;
+ else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
+ m->destination = NULL;
+ else if (k->dst_id == KDBUS_DST_ID_NAME)
+ m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
+ else {
+ snprintf(m->destination_buffer, sizeof(m->destination_buffer), ":1.%llu", (unsigned long long) k->dst_id);
+ m->destination = m->destination_buffer;
}
/* We take possession of the kmsg struct now */
return fd;
}
+
+int bus_kernel_try_close(sd_bus *bus) {
+ assert(bus);
+ assert(bus->is_kernel);
+
+ if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE) < 0)
+ return -errno;
+
+ return 0;
+}