X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-message.c;h=ceac15601e1edf35e8c0e48a70256143529f72f4;hb=66b26c5c9b02e787bc46db24daff04ad41e05ec5;hp=747b44ac942944711c28879670a8ac30baf5fc9e;hpb=453a0c2946da620f99825d39db335e9ea9861829;p=elogind.git diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 747b44ac9..ceac15601 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -59,6 +59,8 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) { assert(part); if (part->memfd >= 0) { + /* If we can reuse the memfd, try that. For that it + * can't be sealed yet. */ if (!part->sealed) bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped); @@ -2184,7 +2186,7 @@ int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, sd_memfd *me return sd_bus_message_close_container(m); } -static int body_part_map_for_read(struct bus_body_part *part) { +int bus_body_part_map(struct bus_body_part *part) { void *p; size_t psz; @@ -2196,6 +2198,13 @@ static int body_part_map_for_read(struct bus_body_part *part) { if (part->size <= 0) return 0; + /* For smaller zero parts (as used for padding) we don't need to map anything... */ + if (part->memfd < 0 && part->is_zero && part->size < 8) { + static const uint8_t zeroes[7] = { }; + part->data = (void*) zeroes; + return 0; + } + psz = PAGE_ALIGN(part->size); if (part->memfd >= 0) @@ -2210,9 +2219,33 @@ static int body_part_map_for_read(struct bus_body_part *part) { part->mapped = psz; part->data = p; + part->munmap_this = true; + return 0; } +void bus_body_part_unmap(struct bus_body_part *part) { + + assert_se(part); + + if (part->memfd < 0) + return; + + if (!part->data) + return; + + if (!part->munmap_this) + return; + + assert_se(munmap(part->data, part->mapped) == 0); + + part->data = NULL; + part->mapped = 0; + part->munmap_this = false; + + return; +} + static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) { size_t k, start, end; @@ -2271,7 +2304,7 @@ static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t s if (index + sz <= begin + part->size) { - r = body_part_map_for_read(part); + r = bus_body_part_map(part); if (r < 0) return NULL; @@ -3208,7 +3241,7 @@ int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, si return align; r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); - if (r < 0) + if (r <= 0) return r; c = message_get_container(m); @@ -3699,19 +3732,27 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) { return r; } - /* Add padding at the end, since we know the body - * needs to start at an 8 byte alignment. */ - + /* Add padding at the end of the fields part, since we know + * the body needs to start at an 8 byte alignment. We made + * sure we allocated enough space for this, so all we need to + * do here is to zero it out. */ l = BUS_MESSAGE_FIELDS_SIZE(m); a = ALIGN8(l) - l; if (a > 0) memset((uint8_t*) BUS_MESSAGE_FIELDS(m) + l, 0, a); - MESSAGE_FOREACH_PART(part, i, m) - if (part->memfd >= 0 && !part->sealed) { - ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1); - part->sealed = true; - } + /* If this is something we can send as memfd, then let's seal + the memfd now. Note that we can send memfds as payload only + for directed messages, and not for broadcasts. */ + if (m->destination) { + MESSAGE_FOREACH_PART(part, i, m) + if (part->memfd >= 0 && !part->sealed && part->size > MEMFD_MIN_SIZE) { + bus_body_part_unmap(part); + + if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0) + part->sealed = true; + } + } m->header->serial = serial; m->sealed = true;