X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-kernel.c;h=878cd9c432f1b022d1098b167756b1915ac42fb2;hp=e5e3536ad076aefd508c50e76a31e38b3638c28b;hb=e86b80b834016d273196c5ec9687fddcddcf9381;hpb=b4da2689995b72fa32c3ba6555c6c3a3f6dce5e2 diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index e5e3536ad..878cd9c43 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,27 @@ 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); - (*d)->size = offsetof(struct kdbus_msg_data, data) + length + 1; + *d = ALIGN8_PTR(*d); + + (*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 + ALIGN8((*d)->size)); + *d = (struct kdbus_msg_data*) ((uint8_t*) *d + (*d)->size); } static int bus_message_setup_kmsg(sd_bus_message *m) { @@ -83,7 +89,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); @@ -105,7 +113,7 @@ static int bus_message_setup_kmsg(sd_bus_message *m) { sz += ALIGN8(offsetof(struct kdbus_msg, data) + dl + 1); } - m->kdbus = malloc0(sz); + m->kdbus = aligned_alloc(8, sz); if (!m->kdbus) return -ENOMEM; @@ -140,9 +148,11 @@ 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; + m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus; assert(m->kdbus->size <= sz); + m->free_kdbus = true; + return 0; } @@ -152,6 +162,9 @@ 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; @@ -160,6 +173,7 @@ int bus_kernel_take_fd(sd_bus *b) { return -ENOMEM; b->is_kernel = true; + b->bus_client = true; r = bus_start_running(b); if (r < 0) @@ -174,6 +188,9 @@ 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 < 0) return -errno; @@ -198,7 +215,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) { @@ -220,6 +237,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); @@ -258,7 +278,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) @@ -282,14 +308,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; } @@ -297,12 +323,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; @@ -316,7 +370,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); @@ -325,13 +379,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; @@ -339,7 +401,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; @@ -351,7 +413,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) { @@ -371,7 +433,7 @@ 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);