X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-message.c;h=0c8604c49257e7c2124ff6fd29620212178fec73;hb=843f737ade9c73609a2280dd3dd16e18222a5dcb;hp=1a461e62e07d5ec6b557fe57d0a0fc8c9297aaf4;hpb=e1c433c6218b3e3bcc2621bdfa575a77017bb9ae;p=elogind.git diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 1a461e62e..0c8604c49 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -65,7 +65,7 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) { * can't be sealed yet. */ if (!part->sealed) - bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped); + bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated); else { if (part->mapped > 0) assert_se(munmap(part->data, part->mapped) == 0); @@ -151,7 +151,7 @@ static void message_free(sd_bus_message *m) { free(m->root_container.signature); free(m->root_container.offsets); - free(m->peeked_signature); + free(m->root_container.peeked_signature); bus_creds_done(&m->creds); free(m); @@ -615,9 +615,9 @@ static int message_new_reply( return -ENOMEM; t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; - t->reply_serial = BUS_MESSAGE_SERIAL(call); + t->reply_cookie = BUS_MESSAGE_COOKIE(call); - r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial); + r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie); if (r < 0) goto fail; @@ -735,7 +735,7 @@ _public_ int sd_bus_message_new_method_errnof( int bus_message_new_synthetic_error( sd_bus *bus, - uint64_t serial, + uint64_t cookie, const sd_bus_error *e, sd_bus_message **m) { @@ -750,9 +750,9 @@ int bus_message_new_synthetic_error( return -ENOMEM; t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; - t->reply_serial = serial; + t->reply_cookie = cookie; - r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial); + r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie); if (r < 0) goto fail; @@ -813,21 +813,21 @@ _public_ int sd_bus_message_get_type(sd_bus_message *m, uint8_t *type) { return 0; } -_public_ int sd_bus_message_get_serial(sd_bus_message *m, uint64_t *serial) { +_public_ int sd_bus_message_get_cookie(sd_bus_message *m, uint64_t *cookie) { assert_return(m, -EINVAL); - assert_return(serial, -EINVAL); - assert_return(m->header->serial != 0, -ENOENT); + assert_return(cookie, -EINVAL); + assert_return(m->header->serial != 0, -ENODATA); - *serial = BUS_MESSAGE_SERIAL(m); + *cookie = BUS_MESSAGE_COOKIE(m); return 0; } -_public_ int sd_bus_message_get_reply_serial(sd_bus_message *m, uint64_t *serial) { +_public_ int sd_bus_message_get_reply_cookie(sd_bus_message *m, uint64_t *cookie) { assert_return(m, -EINVAL); - assert_return(serial, -EINVAL); - assert_return(m->reply_serial != 0, -ENOENT); + assert_return(cookie, -EINVAL); + assert_return(m->reply_cookie != 0, -ENODATA); - *serial = m->reply_serial; + *cookie = m->reply_cookie; return 0; } @@ -1049,20 +1049,27 @@ static int part_make_space( return -ENOMEM; if (!part->data && part->memfd < 0) - part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped); + part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated); if (part->memfd >= 0) { - uint64_t u = sz; - r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &u); - if (r < 0) { - m->poisoned = true; - return -errno; + if (part->allocated == 0 || sz > part->allocated) { + uint64_t new_allocated; + + new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1); + r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated); + if (r < 0) { + m->poisoned = true; + return -errno; + } + + part->allocated = new_allocated; } if (!part->data || sz > part->mapped) { - size_t psz = PAGE_ALIGN(sz > 0 ? sz : 1); + size_t psz; + psz = PAGE_ALIGN(sz > 0 ? sz : 1); if (part->mapped <= 0) n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0); else @@ -1079,14 +1086,20 @@ static int part_make_space( part->munmap_this = true; } else { - n = realloc(part->data, MAX(sz, 1u)); - if (!n) { - m->poisoned = true; - return -ENOMEM; - } + if (part->allocated == 0 || sz > part->allocated) { + size_t new_allocated; - part->data = n; - part->free_this = true; + new_allocated = sz > 0 ? 2 * sz : 64; + n = realloc(part->data, new_allocated); + if (!n) { + m->poisoned = true; + return -ENOMEM; + } + + part->data = n; + part->allocated = new_allocated; + part->free_this = true; + } } if (q) @@ -1420,7 +1433,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void *stored = (const uint8_t*) a + 4; } else if (type == SD_BUS_TYPE_SIGNATURE) { - *(uint8_t*) a = sz - 1; + *(uint8_t*) a = sz - 2; memcpy((uint8_t*) a + 1, p, sz - 1); if (stored) @@ -2042,7 +2055,7 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, return r; } - assert(i <= c->n_offsets); + assert(!c->need_offsets || i <= c->n_offsets); /* We need to add an offset for each item that has a * variable size and that is not the last one in the @@ -2054,7 +2067,8 @@ static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, p += n; } - assert(i == c->n_offsets); + assert(!c->need_offsets || i == c->n_offsets); + assert(c->need_offsets || n_variable == 0); if (n_variable <= 0) { a = message_extend_body(m, 1, 0, add_offset); @@ -2693,7 +2707,7 @@ static int bus_message_close_header(sd_bus_message *m) { return 0; } -int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout) { +int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) { struct bus_body_part *part; size_t l, a; unsigned i; @@ -2739,7 +2753,7 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout) { if (r < 0) return r; - m->header->serial = serial; + m->header->serial = (uint32_t) cookie; m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout; /* Add padding at the end of the fields part, since we know @@ -2757,8 +2771,19 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial, usec_t timeout) { if (m->destination && m->bus && m->bus->use_memfd) { MESSAGE_FOREACH_PART(part, i, m) if (part->memfd >= 0 && !part->sealed && (part->size > MEMFD_MIN_SIZE || m->bus->use_memfd < 0)) { + uint64_t sz; + + /* Try to seal it if that makes + * sense. First, unmap our own map to + * make sure we don't keep it busy. */ bus_body_part_unmap(part); + /* Then, sync up real memfd size */ + sz = part->size; + if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0) + return -errno; + + /* Finally, try to seal */ if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0) part->sealed = true; } @@ -3891,6 +3916,7 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m, w = m->containers + m->n_containers++; w->enclosing = type; w->signature = signature; + w->peeked_signature = NULL; w->index = 0; w->before = before; @@ -3935,6 +3961,7 @@ _public_ int sd_bus_message_exit_container(sd_bus_message *m) { } free(c->signature); + free(c->peeked_signature); free(c->offsets); m->n_containers--; @@ -4012,10 +4039,8 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (!sig) return -ENOMEM; - free(m->peeked_signature); - m->peeked_signature = sig; - - *contents = sig; + free(c->peeked_signature); + *contents = c->peeked_signature = sig; } if (type) @@ -4040,10 +4065,8 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (!sig) return -ENOMEM; - free(m->peeked_signature); - m->peeked_signature = sig; - - *contents = sig; + free(c->peeked_signature); + *contents = c->peeked_signature = sig; } if (type) @@ -4083,15 +4106,15 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (k > c->item_size) return -EBADMSG; - free(m->peeked_signature); - m->peeked_signature = strndup((char*) q + 1, k - 1); - if (!m->peeked_signature) + free(c->peeked_signature); + c->peeked_signature = strndup((char*) q + 1, k - 1); + if (!c->peeked_signature) return -ENOMEM; - if (!signature_is_valid(m->peeked_signature, true)) + if (!signature_is_valid(c->peeked_signature, true)) return -EBADMSG; - *contents = m->peeked_signature; + *contents = c->peeked_signature; } else { size_t rindex, l; @@ -5037,17 +5060,17 @@ int bus_message_parse_fields(sd_bus_message *m) { } case BUS_MESSAGE_HEADER_REPLY_SERIAL: - if (m->reply_serial != 0) + if (m->reply_cookie != 0) return -EBADMSG; if (!streq(signature, "u")) return -EBADMSG; - r = message_peek_field_uint32(m, &ri, item_size, &m->reply_serial); + r = message_peek_field_uint32(m, &ri, item_size, &m->reply_cookie); if (r < 0) return r; - if (m->reply_serial == 0) + if (m->reply_cookie == 0) return -EBADMSG; break; @@ -5098,17 +5121,25 @@ int bus_message_parse_fields(sd_bus_message *m) { case SD_BUS_MESSAGE_METHOD_RETURN: - if (m->reply_serial == 0) + if (m->reply_cookie == 0) return -EBADMSG; break; case SD_BUS_MESSAGE_METHOD_ERROR: - if (m->reply_serial == 0 || !m->error.name) + if (m->reply_cookie == 0 || !m->error.name) return -EBADMSG; break; } + /* Refuse non-local messages that claim they are local */ + if (streq_ptr(m->path, "/org/freedesktop/DBus/Local")) + return -EBADMSG; + if (streq_ptr(m->interface, "org.freedesktop.DBus.Local")) + return -EBADMSG; + if (streq_ptr(m->sender, "org.freedesktop.DBus.Local")) + return -EBADMSG; + m->root_container.end = BUS_MESSAGE_BODY_SIZE(m); if (BUS_MESSAGE_IS_GVARIANT(m)) { @@ -5441,8 +5472,8 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { if (!n) return -ENOMEM; - n->reply_serial = (*m)->reply_serial; - r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_serial); + n->reply_cookie = (*m)->reply_cookie; + r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_cookie); if (r < 0) return r; @@ -5482,7 +5513,7 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { if (timeout == 0 && !((*m)->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)) timeout = BUS_DEFAULT_TIMEOUT; - r = bus_message_seal(n, (*m)->header->serial, timeout); + r = bus_message_seal(n, BUS_MESSAGE_COOKIE(*m), timeout); if (r < 0) return r; @@ -5492,3 +5523,13 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { return 0; } + +int bus_message_append_sender(sd_bus_message *m, const char *sender) { + assert(m); + assert(sender); + + assert_return(!m->sealed, -EPERM); + assert_return(!m->sender, -EPERM); + + return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender); +}