#include <fcntl.h>
#include <malloc.h>
#include <sys/mman.h>
+#include <sys/prctl.h>
#include "util.h"
#include "strv.h"
assert(m);
assert(m->sealed);
+ /* We put this together only once, if this message is reused
+ * we reuse the earlier-built version */
if (m->kdbus)
return 0;
case KDBUS_ITEM_TIMESTAMP:
m->realtime = d->timestamp.realtime_ns / NSEC_PER_USEC;
m->monotonic = d->timestamp.monotonic_ns / NSEC_PER_USEC;
+ m->seqnum = d->timestamp.seqnum;
break;
case KDBUS_ITEM_PID_COMM:
int bus_kernel_take_fd(sd_bus *b) {
struct kdbus_cmd_hello *hello;
struct kdbus_item *item;
- size_t l = 0, sz;
+ _cleanup_free_ char *g = NULL;
+ const char *name;
+ size_t l = 0, m = 0, sz;
int r;
assert(b);
b->use_memfd = 1;
- sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items));
+ if (b->connection_name) {
+ g = sd_bus_label_escape(b->connection_name);
+ if (!g)
+ return -ENOMEM;
+
+ name = g;
+ } else {
+ char pr[17] = {};
+
+ /* If no name is explicitly set, we'll include a hint
+ * indicating the library implementation, a hint which
+ * kind of bus this is and the thread name */
+
+ assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
+
+ if (isempty(pr)) {
+ name = b->is_system ? "sd-system" :
+ b->is_user ? "sd-user" : "sd";
+ } else {
+ _cleanup_free_ char *e = NULL;
+
+ e = sd_bus_label_escape(pr);
+ if (!e)
+ return -ENOMEM;
+
+ g = strappend(b->is_system ? "sd-system-" :
+ b->is_user ? "sd-user-" : "sd-",
+ e);
+ if (!g)
+ return -ENOMEM;
+
+ name = g;
+ }
+
+ b->connection_name = sd_bus_label_unescape(name);
+ if (!b->connection_name)
+ return -ENOMEM;
+ }
+
+ m = strlen(name);
+
+ sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
+ ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
if (b->fake_creds_valid)
- sz += ALIGN8(offsetof(struct kdbus_item, creds)) + sizeof(struct kdbus_creds);
+ sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
if (b->fake_label) {
l = strlen(b->fake_label);
item = hello->items;
+ item->size = offsetof(struct kdbus_item, str) + m + 1;
+ item->type = KDBUS_ITEM_CONN_NAME;
+ memcpy(item->str, name, m + 1);
+ item = KDBUS_ITEM_NEXT(item);
+
if (b->fake_creds_valid) {
item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
item->type = KDBUS_ITEM_CREDS;
if (b->fake_label) {
item->size = offsetof(struct kdbus_item, str) + l + 1;
+ item->type = KDBUS_ITEM_SECLABEL;
memcpy(item->str, b->fake_label, l+1);
}
return bus_kernel_take_fd(b);
}
-int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) {
+static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
+ uint64_t off;
+ struct kdbus_item *d;
+
+ assert(bus);
+ assert(k);
+
+ off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
+ ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
+
+ KDBUS_ITEM_FOREACH(d, k, items) {
+
+ if (d->type == KDBUS_ITEM_FDS)
+ close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
+ else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
+ close_nointr_nofail(d->memfd.fd);
+ }
+}
+
+int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
int r;
assert(bus);
if (r < 0)
return r;
+ /* 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;
+
r = ioctl(bus->output_fd, KDBUS_CMD_MSG_SEND, m->kdbus);
if (r < 0) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
bus->rqueue[bus->rqueue_size++] = reply;
- return 0;
- }
-
- return 1;
-}
-
-static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
- uint64_t off;
- struct kdbus_item *d;
+ } else if (hint_sync_call) {
+ struct kdbus_msg *k;
- assert(bus);
- assert(k);
+ k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + m->kdbus->offset_reply);
+ assert(k);
- off = (uint8_t *)k - (uint8_t *)bus->kdbus_buffer;
- ioctl(bus->input_fd, KDBUS_CMD_FREE, &off);
+ if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
- KDBUS_ITEM_FOREACH(d, k, items) {
+ r = bus_kernel_make_message(bus, k);
+ if (r < 0) {
+ close_kdbus_msg(bus, k);
- if (d->type == KDBUS_ITEM_FDS)
- close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
- else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
- close_nointr_nofail(d->memfd.fd);
+ /* Anybody can send us invalid messages, let's just drop them. */
+ if (r == -EBADMSG || r == -EPROTOTYPE)
+ log_debug("Ignoring invalid message: %s", strerror(-r));
+ else
+ return r;
+ }
+ } else {
+ log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
+ close_kdbus_msg(bus, k);
+ }
}
+
+ return 1;
}
static int push_name_owner_changed(sd_bus *bus, const char *name, const char *old_owner, const char *new_owner) {
return -errno;
}
- k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset);
+ k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.offset);
if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
r = bus_kernel_make_message(bus, k);
} else if (k->payload_type == KDBUS_PAYLOAD_KERNEL)
r = bus_kernel_translate_message(bus, k);
- else
+ else {
+ log_debug("Ignoring message with unknown payload type %llu.", (unsigned long long) k->payload_type);
r = 0;
+ }
if (r <= 0)
close_kdbus_msg(bus, k);