X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-kernel.c;h=a0e892a49f769ad8ebd3bd8a4f9fb0fb4464b8d1;hp=3aa408414ee3f79029d5e090e4f17bb4d2021b91;hb=a392d36195f92eaa2d5b7c1d588ff8e52025a43a;hpb=9b29bb6853987bf6fef21531f69864fdfb39eb9a diff --git a/src/libsystemd-bus/bus-kernel.c b/src/libsystemd-bus/bus-kernel.c index 3aa408414..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); @@ -210,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 */ @@ -249,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)); - if (m->fields) - append_payload_vec(&d, m->fields, ALIGN8(m->header->fields_size)); + 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 (!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; + } - MESSAGE_FOREACH_PART(part, i, m) 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) @@ -278,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) { @@ -398,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; @@ -439,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); + + if (!bus_header_is_complete(h, d->vec.size)) + return -EBADMSG; } n_payload++; @@ -470,7 +490,7 @@ 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; @@ -489,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; @@ -507,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; } @@ -551,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)) { - sd_bus_message_unref(m); - return -EBADMSG; - } - r = bus_message_parse_fields(m); if (r < 0) { sd_bus_message_unref(m);