X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-message.c;h=0f9334bb843c6389b9db9115f5260667b4fc3e43;hb=d95eb43e90f19ff0c9aaff1c5fb1a7ed9fbd89a5;hp=1a8c445f0bc519940d1c4155330ed9d7b10a0004;hpb=022fb8558e797483709ab3e9fe846f04f7026dac;p=elogind.git diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 1a8c445f0..0f9334bb8 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -65,17 +65,19 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) { /* If we can reuse the memfd, try that. For that it * can't be sealed yet. */ - if (!part->sealed) + if (!part->sealed) { + assert(part->memfd_offset == 0); + assert(part->data == part->mmap_begin); bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated); - else { + } else { if (part->mapped > 0) - assert_se(munmap(part->data, part->mapped) == 0); + assert_se(munmap(part->mmap_begin, part->mapped) == 0); safe_close(part->memfd); } } else if (part->munmap_this) - munmap(part->data, part->mapped); + munmap(part->mmap_begin, part->mapped); else if (part->free_this) free(part->data); @@ -128,8 +130,9 @@ static void message_free(sd_bus_message *m) { message_reset_parts(m); if (m->release_kdbus) { - struct kdbus_cmd_free cmd_free; + struct kdbus_cmd_free cmd_free = { }; + cmd_free.size = sizeof(cmd_free); cmd_free.flags = 0; cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer; (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free); @@ -420,10 +423,20 @@ int bus_message_from_header( m->n_fds = n_fds; if (ucred) { - m->creds.uid = ucred->uid; m->creds.pid = ucred->pid; + m->creds.uid = ucred->uid; m->creds.gid = ucred->gid; - m->creds.mask |= SD_BUS_CREDS_UID | SD_BUS_CREDS_PID | SD_BUS_CREDS_GID; + + /* Due to namespace translations some data might be + * missing from this ucred record. */ + if (m->creds.pid > 0) + m->creds.mask |= SD_BUS_CREDS_PID; + + if (m->creds.uid != UID_INVALID) + m->creds.mask |= SD_BUS_CREDS_UID; + + if (m->creds.gid != GID_INVALID) + m->creds.mask |= SD_BUS_CREDS_GID; } if (label) { @@ -1093,8 +1106,10 @@ static int part_make_space( if (m->poisoned) return -ENOMEM; - if (!part->data && part->memfd < 0) + if (!part->data && part->memfd < 0) { part->memfd = bus_kernel_pop_memfd(m->bus, &part->data, &part->mapped, &part->allocated); + part->mmap_begin = part->data; + } if (part->memfd >= 0) { @@ -1118,15 +1133,16 @@ static int part_make_space( if (part->mapped <= 0) n = mmap(NULL, psz, PROT_READ|PROT_WRITE, MAP_SHARED, part->memfd, 0); else - n = mremap(part->data, part->mapped, psz, MREMAP_MAYMOVE); + n = mremap(part->mmap_begin, part->mapped, psz, MREMAP_MAYMOVE); if (n == MAP_FAILED) { m->poisoned = true; return -errno; } + part->mmap_begin = part->data = n; part->mapped = psz; - part->data = n; + part->memfd_offset = 0; } part->munmap_this = true; @@ -1335,7 +1351,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void } else { char *e; - /* Maybe we can append to the signature? But only if this is the top-level container*/ + /* Maybe we can append to the signature? But only if this is the top-level container */ if (c->enclosing != 0) return -ENXIO; @@ -1528,7 +1544,7 @@ _public_ int sd_bus_message_append_string_space( } else { char *e; - /* Maybe we can append to the signature? But only if this is the top-level container*/ + /* Maybe we can append to the signature? But only if this is the top-level container */ if (c->enclosing != 0) return -ENXIO; @@ -2053,6 +2069,7 @@ static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) assert(m); assert(c); + assert(c->signature); if (!BUS_MESSAGE_IS_GVARIANT(m)) return 0; @@ -2492,10 +2509,11 @@ _public_ int sd_bus_message_append_array_space( return 0; } -_public_ int sd_bus_message_append_array(sd_bus_message *m, - char type, - const void *ptr, - size_t size) { +_public_ int sd_bus_message_append_array( + sd_bus_message *m, + char type, + const void *ptr, + size_t size) { int r; void *p; @@ -2551,26 +2569,26 @@ _public_ int sd_bus_message_append_array_iovec( return 0; } -_public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, - char type, - int memfd) { +_public_ int sd_bus_message_append_array_memfd( + sd_bus_message *m, + char type, + int memfd, + uint64_t offset, + uint64_t size) { + _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; ssize_t align, sz; - uint64_t size; + uint64_t real_size; void *a; int r; - if (!m) - return -EINVAL; - if (memfd < 0) - return -EINVAL; - if (m->sealed) - return -EPERM; - if (!bus_type_is_trivial(type)) - return -EINVAL; - if (m->poisoned) - return -ESTALE; + assert_return(m, -EINVAL); + assert_return(memfd >= 0, -EINVAL); + assert_return(bus_type_is_trivial(type), -EINVAL); + assert_return(size > 0, -EINVAL); + assert_return(!m->sealed, -EPERM); + assert_return(!m->poisoned, -ESTALE); r = memfd_set_sealed(memfd); if (r < 0) @@ -2580,16 +2598,24 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, if (copy_fd < 0) return copy_fd; - r = memfd_get_size(memfd, &size); + r = memfd_get_size(memfd, &real_size); if (r < 0) return r; + if (offset == 0 && size == (uint64_t) -1) + size = real_size; + else if (offset + size > real_size) + return -EMSGSIZE; + align = bus_type_get_alignment(type); sz = bus_type_get_size(type); assert_se(align > 0); assert_se(sz > 0); + if (offset % align != 0) + return -EINVAL; + if (size % sz != 0) return -EINVAL; @@ -2609,6 +2635,7 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, return -ENOMEM; part->memfd = copy_fd; + part->memfd_offset = offset; part->sealed = true; part->size = size; copy_fd = -1; @@ -2619,16 +2646,22 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, return sd_bus_message_close_container(m); } -_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) { +_public_ int sd_bus_message_append_string_memfd( + sd_bus_message *m, + int memfd, + uint64_t offset, + uint64_t size) { + _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; struct bus_container *c; - uint64_t size; + uint64_t real_size; void *a; int r; assert_return(m, -EINVAL); assert_return(memfd >= 0, -EINVAL); + assert_return(size > 0, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); @@ -2640,10 +2673,15 @@ _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) { if (copy_fd < 0) return copy_fd; - r = memfd_get_size(memfd, &size); + r = memfd_get_size(memfd, &real_size); if (r < 0) return r; + if (offset == 0 && size == (uint64_t) -1) + size = real_size; + else if (offset + size > real_size) + return -EMSGSIZE; + /* We require this to be NUL terminated */ if (size == 0) return -EINVAL; @@ -2660,7 +2698,7 @@ _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) { } else { char *e; - /* Maybe we can append to the signature? But only if this is the top-level container*/ + /* Maybe we can append to the signature? But only if this is the top-level container */ if (c->enclosing != 0) return -ENXIO; @@ -2684,6 +2722,7 @@ _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) { return -ENOMEM; part->memfd = copy_fd; + part->memfd_offset = offset; part->sealed = true; part->size = size; copy_fd = -1; @@ -2847,7 +2886,7 @@ int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) { int bus_body_part_map(struct bus_body_part *part) { void *p; - size_t psz; + size_t psz, shift; assert_se(part); @@ -2864,10 +2903,11 @@ int bus_body_part_map(struct bus_body_part *part) { return 0; } - psz = PAGE_ALIGN(part->size); + shift = part->memfd_offset - ((part->memfd_offset / page_size()) * page_size()); + psz = PAGE_ALIGN(part->size + shift); if (part->memfd >= 0) - p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0); + p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, part->memfd_offset - shift); else if (part->is_zero) p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); else @@ -2877,7 +2917,8 @@ int bus_body_part_map(struct bus_body_part *part) { return -errno; part->mapped = psz; - part->data = p; + part->mmap_begin = p; + part->data = (uint8_t*) p + shift; part->munmap_this = true; return 0; @@ -2890,14 +2931,15 @@ void bus_body_part_unmap(struct bus_body_part *part) { if (part->memfd < 0) return; - if (!part->data) + if (!part->mmap_begin) return; if (!part->munmap_this) return; - assert_se(munmap(part->data, part->mapped) == 0); + assert_se(munmap(part->mmap_begin, part->mapped) == 0); + part->mmap_begin = NULL; part->data = NULL; part->mapped = 0; part->munmap_this = false; @@ -4440,13 +4482,32 @@ _public_ int sd_bus_message_skip(sd_bus_message *m, const char *types) { assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); - assert_return(types, -EINVAL); - if (isempty(types)) - return 0; + /* If types is NULL, read exactly one element */ + if (!types) { + struct bus_container *c; + size_t l; + + if (message_end_of_signature(m)) + return -ENXIO; + + if (message_end_of_array(m, m->rindex)) + return 0; + + c = message_get_container(m); + + r = signature_element_length(c->signature + c->index, &l); + if (r < 0) + return r; + + types = strndupa(c->signature + c->index, l); + } switch (*types) { + case 0: /* Nothing to drop */ + return 0; + case SD_BUS_TYPE_BYTE: case SD_BUS_TYPE_BOOLEAN: case SD_BUS_TYPE_INT16: @@ -5160,6 +5221,10 @@ int bus_message_parse_fields(sd_bus_message *m) { case SD_BUS_MESSAGE_SIGNAL: if (!m->path || !m->interface || !m->member) return -EBADMSG; + + if (m->reply_cookie != 0) + return -EBADMSG; + break; case SD_BUS_MESSAGE_METHOD_CALL: @@ -5167,6 +5232,9 @@ int bus_message_parse_fields(sd_bus_message *m) { if (!m->path || !m->member) return -EBADMSG; + if (m->reply_cookie != 0) + return -EBADMSG; + break; case SD_BUS_MESSAGE_METHOD_RETURN: @@ -5297,35 +5365,57 @@ _public_ int sd_bus_message_read_strv(sd_bus_message *m, char ***l) { return 1; } -const char* bus_message_get_arg(sd_bus_message *m, unsigned i) { - int r; - const char *t = NULL; +int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str, char ***strv) { + const char *contents; unsigned j; + char type; + int r; assert(m); + assert(str); + assert(strv); r = sd_bus_message_rewind(m, true); if (r < 0) - return NULL; + return r; - for (j = 0; j <= i; j++) { - char type; + for (j = 0;; j++) { + r = sd_bus_message_peek_type(m, &type, &contents); + if (r < 0) + return r; + if (r == 0) + return -ENXIO; + + /* Don't match against arguments after the first one we don't understand */ + if (!IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE) && + !(type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g"))) + return -ENXIO; + + if (j >= i) + break; - r = sd_bus_message_peek_type(m, &type, NULL); + r = sd_bus_message_skip(m, NULL); if (r < 0) - return NULL; + return r; + } - if (type != SD_BUS_TYPE_STRING && - type != SD_BUS_TYPE_OBJECT_PATH && - type != SD_BUS_TYPE_SIGNATURE) - return NULL; + if (type == SD_BUS_TYPE_ARRAY) { - r = sd_bus_message_read_basic(m, type, &t); + r = sd_bus_message_read_strv(m, strv); if (r < 0) - return NULL; + return r; + + *str = NULL; + + } else { + r = sd_bus_message_read_basic(m, type, str); + if (r < 0) + return r; + + *strv = NULL; } - return t; + return 0; } bool bus_header_is_complete(struct bus_header *h, size_t size) { @@ -5380,6 +5470,18 @@ _public_ const char* sd_bus_message_get_signature(sd_bus_message *m, int complet return strempty(c->signature); } +_public_ int sd_bus_message_is_empty(sd_bus_message *m) { + assert_return(m, -EINVAL); + + return isempty(m->root_container.signature); +} + +_public_ int sd_bus_message_has_signature(sd_bus_message *m, const char *signature) { + assert_return(m, -EINVAL); + + return streq(strempty(m->root_container.signature), strempty(signature)); +} + _public_ int sd_bus_message_copy(sd_bus_message *m, sd_bus_message *source, int all) { bool done_something = false; int r;