X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-kernel.c;h=7918aeab191d8d1342d2f41227231525c0936992;hb=b5baa8fe8838870cc2bd7cef0949299f061ae15d;hp=c10fcc54df1c12ae11fc6a29c625bf0543bbd952;hpb=6629161f827c82889cf45cfcdce62dcb543eda23;p=elogind.git diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index c10fcc54d..7918aeab1 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -19,6 +19,10 @@ along with systemd; If not, see . ***/ +#ifdef HAVE_VALGRIND_MEMCHECK_H +#include +#endif + #include #include "util.h" @@ -32,8 +36,6 @@ (uint8_t*) (d) < (uint8_t*) (k) + (k)->size; \ (d) = (struct kdbus_msg_data*) ((uint8_t*) (d) + ALIGN8((d)->size))) - - static int parse_unique_name(const char *s, uint64_t *id) { int r; @@ -55,23 +57,40 @@ static void append_payload_vec(struct kdbus_msg_data **d, const void *p, size_t assert(p); assert(sz > 0); + *d = ALIGN8_PTR(*d); + (*d)->size = offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec); (*d)->type = KDBUS_MSG_PAYLOAD_VEC; (*d)->vec.address = (uint64_t) p; (*d)->vec.size = sz; - *d = (struct kdbus_msg_data*) ((uint8_t*) *d + ALIGN8((*d)->size)); + *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); } static void append_destination(struct kdbus_msg_data **d, const char *s, size_t length) { assert(d); - assert(d); + assert(s); + + *d = ALIGN8_PTR(*d); - (*d)->size = offsetof(struct kdbus_msg_data, data) + length + 1; + (*d)->size = offsetof(struct kdbus_msg_data, str) + length + 1; (*d)->type = KDBUS_MSG_DST_NAME; - memcpy((*d)->data, s, length + 1); + memcpy((*d)->str, s, length + 1); + + *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); +} + +static void append_bloom(struct kdbus_msg_data **d, const void *p, size_t length) { + assert(d); + assert(p); + + *d = ALIGN8_PTR(*d); - *d = (struct kdbus_msg_data*) ((uint8_t*) *d + ALIGN8((*d)->size)); + (*d)->size = offsetof(struct kdbus_msg_data, data) + length; + (*d)->type = KDBUS_MSG_BLOOM; + memcpy((*d)->data, p, length); + + *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); } static int bus_message_setup_kmsg(sd_bus_message *m) { @@ -83,7 +102,9 @@ static int bus_message_setup_kmsg(sd_bus_message *m) { assert(m); assert(m->sealed); - assert(!m->kdbus); + + if (m->kdbus) + return 0; if (m->destination) { r = parse_unique_name(m->destination, &unique); @@ -99,22 +120,26 @@ static int bus_message_setup_kmsg(sd_bus_message *m) { /* Add in fixed header, fields header, fields header padding and payload */ sz += 4 * ALIGN8(offsetof(struct kdbus_msg_data, vec) + sizeof(struct kdbus_vec)); + sz += ALIGN8(offsetof(struct kdbus_msg_data, data) + 5); + /* Add in well-known destination header */ if (well_known) { dl = strlen(m->destination); sz += ALIGN8(offsetof(struct kdbus_msg, data) + dl + 1); } - m->kdbus = malloc0(sz); + m->kdbus = aligned_alloc(8, sz); if (!m->kdbus) return -ENOMEM; + memset(m->kdbus, 0, sz); + m->kdbus->flags = ((m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) | ((m->header->flags & SD_BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0); m->kdbus->dst_id = well_known ? 0 : - m->destination ? unique : (uint64_t) -1; + m->destination ? unique : KDBUS_DST_ID_BROADCAST; m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS1; m->kdbus->cookie = m->header->serial; @@ -140,9 +165,14 @@ static int bus_message_setup_kmsg(sd_bus_message *m) { if (m->body) append_payload_vec(&d, m->body, m->header->body_size); - m->kdbus->size = (uint8_t*) m - (uint8_t*) m->kdbus; + if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) + append_bloom(&d, "bloom", 5); + + m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus; assert(m->kdbus->size <= sz); + m->free_kdbus = true; + return 0; } @@ -152,11 +182,18 @@ int bus_kernel_take_fd(sd_bus *b) { assert(b); + if (b->is_server) + return -EINVAL; + r = ioctl(b->input_fd, KDBUS_CMD_HELLO, &hello); if (r < 0) return -errno; + if (asprintf(&b->unique_name, ":1.%llu", (unsigned long long) hello.id) < 0) + return -ENOMEM; + b->is_kernel = true; + b->bus_client = true; r = bus_start_running(b); if (r < 0) @@ -171,8 +208,11 @@ int bus_kernel_connect(sd_bus *b) { assert(b->output_fd < 0); assert(b->kernel); + if (b->is_server) + return -EINVAL; + b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC); - if (b->input_fd) + if (b->input_fd < 0) return -errno; b->output_fd = b->input_fd; @@ -195,7 +235,7 @@ int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m) { if (r < 0) return errno == EAGAIN ? 0 : -errno; - return 0; + return 1; } static void close_kdbus_msg(struct kdbus_msg *k) { @@ -217,6 +257,9 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess _cleanup_free_ int *fds = NULL; struct bus_header *h = NULL; size_t total, n_bytes = 0, idx = 0; + struct kdbus_creds *creds = NULL; + uint64_t nsec = 0; + const char *destination = NULL; int r; assert(bus); @@ -255,7 +298,13 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess fds = f; memcpy(fds + n_fds, d->fds, j); n_fds += j; - } + + } else if (d->type == KDBUS_MSG_SRC_CREDS) + creds = &d->creds; + else if (d->type == KDBUS_MSG_TIMESTAMP) + nsec = d->ts_ns; + else if (d->type == KDBUS_MSG_DST_NAME) + destination = d->str; } if (!h) @@ -279,14 +328,14 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess continue; l = d->size - offsetof(struct kdbus_msg_data, data); - if (idx == sizeof(struct bus_header) && l == BUS_MESSAGE_FIELDS_SIZE(m)) m->fields = d->data; else if (idx == sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)) && l == BUS_MESSAGE_BODY_SIZE(m)) m->body = d->data; - else { + else if (!(idx == 0 && l == sizeof(struct bus_header)) && + !(idx == sizeof(struct bus_header) + BUS_MESSAGE_FIELDS_SIZE(m))) { sd_bus_message_unref(m); return -EBADMSG; } @@ -294,12 +343,40 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess idx += l; } + if (creds) { + m->pid_starttime = creds->starttime / NSEC_PER_USEC; + m->uid = creds->uid; + m->gid = creds->gid; + m->pid = creds->pid; + m->tid = creds->tid; + m->uid_valid = m->gid_valid = true; + } + + m->timestamp = nsec / NSEC_PER_USEC; + r = bus_message_parse_fields(m); if (r < 0) { sd_bus_message_unref(m); return r; } + if (k->src_id == KDBUS_SRC_ID_KERNEL) + m->sender = "org.freedesktop.DBus"; + else { + snprintf(m->sender_buffer, sizeof(m->sender_buffer), ":1.%llu", (unsigned long long) k->src_id); + m->sender = m->sender_buffer; + } + + if (!m->destination) { + if (destination) + m->destination = destination; + else if (k->dst_id != KDBUS_DST_ID_WELL_KNOWN_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; + } + } + /* We take possession of the kmsg struct now */ m->kdbus = k; m->free_kdbus = true; @@ -313,7 +390,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) { struct kdbus_msg *k; - size_t sz = 128; + size_t sz = 1024; int r; assert(bus); @@ -322,13 +399,21 @@ int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) { for (;;) { void *q; - q = realloc(bus->rbuffer, sz); + q = aligned_alloc(8, sz); if (!q) return -errno; + free(bus->rbuffer); k = bus->rbuffer = q; k->size = sz; + /* Let's tell valgrind that there's really no need to + * initialize this fully. This should be removed again + * when valgrind learned the kdbus ioctls natively. */ +#ifdef HAVE_VALGRIND_MEMCHECK_H + VALGRIND_MAKE_MEM_DEFINED(k, sz); +#endif + r = ioctl(bus->input_fd, KDBUS_CMD_MSG_RECV, bus->rbuffer); if (r >= 0) break; @@ -336,7 +421,7 @@ int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) { if (errno == EAGAIN) return 0; - if (errno != -EMSGSIZE) + if (errno != ENOBUFS) return -errno; sz *= 2; @@ -348,7 +433,7 @@ int bus_kernel_read_message(sd_bus *bus, sd_bus_message **m) { else close_kdbus_msg(k); - return r; + return r < 0 ? r : 1; } int bus_kernel_create(const char *name, char **s) { @@ -368,14 +453,14 @@ int bus_kernel_create(const char *name, char **s) { fname = alloca(offsetof(struct kdbus_cmd_fname, name) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1); sprintf(fname->name, "%lu-%s", (unsigned long) getuid(), name); fname->size = offsetof(struct kdbus_cmd_fname, name) + strlen(fname->name) + 1; - fname->kernel_flags = KDBUS_CMD_FNAME_ACCESS_WORLD; + fname->kernel_flags = KDBUS_CMD_FNAME_ACCESS_WORLD | KDBUS_CMD_FNAME_POLICY_OPEN; fname->user_flags = 0; p = strjoin("/dev/kdbus/", fname->name, "/bus", NULL); if (!p) return -ENOMEM; - if (ioctl(fd, KDBUS_CMD_BUS_MAKE, &fname) < 0) { + if (ioctl(fd, KDBUS_CMD_BUS_MAKE, fname) < 0) { close_nointr_nofail(fd); free(p); return -errno;