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);
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;
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)
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;
if (index + sz <= begin + part->size) {
- r = body_part_map_for_read(part);
+ r = bus_body_part_map(part);
if (r < 0)
return NULL;
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);
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;