X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-kernel.c;h=a0e892a49f769ad8ebd3bd8a4f9fb0fb4464b8d1;hb=a392d36195f92eaa2d5b7c1d588ff8e52025a43a;hp=b11df300b6020781f190884b18d44d613c257299;hpb=bc7fd8cdbef54ebd3902cdd455ecad3e095f7450;p=elogind.git diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index b11df300b..a0e892a49 100644 --- a/src/libsystemd-bus/bus-kernel.c +++ b/src/libsystemd-bus/bus-kernel.c @@ -65,19 +65,32 @@ static int parse_unique_name(const char *s, uint64_t *id) { static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) { assert(d); - assert(p); assert(sz > 0); *d = ALIGN8_PTR(*d); (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec); (*d)->type = KDBUS_MSG_PAYLOAD_VEC; - (*d)->vec.address = (uint64_t) p; + (*d)->vec.address = PTR_TO_UINT64(p); (*d)->vec.size = sz; *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); } +static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t sz) { + assert(d); + assert(memfd >= 0); + assert(sz > 0); + + *d = ALIGN8_PTR(*d); + (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd); + (*d)->type = KDBUS_MSG_PAYLOAD_MEMFD; + (*d)->memfd.fd = memfd; + (*d)->memfd.size = sz; + + *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size); +} + static void append_destination(struct kdbus_item **d, const char *s, size_t length) { assert(d); assert(s); @@ -184,12 +197,13 @@ static int bus_message_setup_bloom(sd_bus_message *m, void *bloom) { } static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { + struct bus_body_part *part; struct kdbus_item *d; bool well_known; uint64_t unique; size_t sz, dl; + unsigned i; int r; - struct bus_body_part *part; assert(b); assert(m); @@ -209,8 +223,11 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { sz = offsetof(struct kdbus_msg, items); + assert_cc(ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)) == + ALIGN8(offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd))); + /* Add in fixed header, fields header and payload */ - sz += (1 + !!m->fields + m->n_body_parts) * + sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec)); /* Add space for bloom filter */ @@ -248,24 +265,39 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { if (well_known) append_destination(&d, m->destination, dl); - append_payload_vec(&d, m->header, sizeof(*m->header)); + append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m)); + + MESSAGE_FOREACH_PART(part, i, m) { + if (part->is_zero) { + append_payload_vec(&d, NULL, part->size); + continue; + } + + if (part->memfd >= 0 && part->sealed) { + bus_body_part_unmap(part); - if (m->fields) - append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size)); + if (!part->data) { + append_payload_memfd(&d, part->memfd, part->size); + continue; + } + } + + if (part->memfd >= 0) { + r = bus_body_part_map(part); + if (r < 0) + goto fail; + } - for (part = &m->body; part && part->size > 0; part = part->next) append_payload_vec(&d, part->data, part->size); + } if (m->kdbus->dst_id == KDBUS_DST_ID_BROADCAST) { void *p; p = append_bloom(&d, BLOOM_SIZE); r = bus_message_setup_bloom(m, p); - if (r < 0) { - free(m->kdbus); - m->kdbus = NULL; - return -r; - } + if (r < 0) + goto fail; } if (m->n_fds > 0) @@ -277,6 +309,11 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { m->free_kdbus = true; return 0; + +fail: + free(m->kdbus); + m->kdbus = NULL; + return r; } int bus_kernel_take_fd(sd_bus *b) { @@ -397,22 +434,6 @@ static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) { } } -static bool range_contains( - size_t astart, size_t asize, - size_t bstart, size_t bsize, - void *a, void **b) { - - if (bstart < astart) - return false; - - if (bstart + bsize > astart + asize) - return false; - - *b = (uint8_t*) a + (bstart - astart); - - return true; -} - static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_message **ret) { sd_bus_message *m = NULL; struct kdbus_item *d; @@ -438,10 +459,10 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess if (d->type == KDBUS_MSG_PAYLOAD_VEC) { if (!h) { - if (d->vec.size < sizeof(struct bus_header)) - return -EBADMSG; + h = UINT64_TO_PTR(d->vec.address); - h = (struct bus_header*)UINT64_TO_PTR(d->vec.address); + if (!bus_header_is_complete(h, d->vec.size)) + return -EBADMSG; } n_payload++; @@ -469,16 +490,13 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess if (!h) return -EBADMSG; - r = bus_header_size(h, &total); + r = bus_header_message_size(h, &total); if (r < 0) return r; if (n_bytes != total) return -EBADMSG; - //if (n_payload > 2) - // return -EBADMSG; - r = bus_message_from_header(h, sizeof(struct bus_header), fds, n_fds, NULL, seclabel, 0, &m); if (r < 0) return r; @@ -491,11 +509,7 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess if (d->type == KDBUS_MSG_PAYLOAD_VEC) { size_t begin_body; - /* Fill in fields material */ - range_contains(idx, d->vec.size, ALIGN8(sizeof(struct bus_header)), BUS_MESSAGE_FIELDS_SIZE(m), - UINT64_TO_PTR(d->vec.address), &m->fields); - - begin_body = ALIGN8(sizeof(struct bus_header)) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)); + begin_body = BUS_MESSAGE_BODY_BEGIN(m); if (idx + d->vec.size > begin_body) { struct bus_body_part *part; @@ -509,13 +523,14 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess } if (idx >= begin_body) { - part->data = (void*) d->vec.address; + part->data = UINT64_TO_PTR(d->vec.address); part->size = d->vec.size; } else { - part->data = (uint8_t*) (uintptr_t) d->vec.address + (begin_body - idx); + part->data = d->vec.address != 0 ? (uint8_t*) UINT64_TO_PTR(d->vec.address) + (begin_body - idx) : NULL; part->size = d->vec.size - (begin_body - idx); } + part->is_zero = d->vec.address == 0; part->sealed = true; } @@ -553,11 +568,6 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k, sd_bus_mess log_debug("Got unknown field from kernel %llu", d->type); } - if ((BUS_MESSAGE_FIELDS_SIZE(m) > 0 && !m->fields) || BUS_MESSAGE_SIZE(m) != idx) { - sd_bus_message_unref(m); - return -EBADMSG; - } - r = bus_message_parse_fields(m); if (r < 0) { sd_bus_message_unref(m); @@ -685,10 +695,10 @@ int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *size) { return -ENOTSUP; if (bus->n_memfd_cache <= 0) { - int fd; + int fd, r; - fd = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd); - if (fd < 0) + r = ioctl(bus->input_fd, KDBUS_CMD_MEMFD_NEW, &fd); + if (r < 0) return -errno; *address = NULL;