X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd%2Fsd-bus%2Fbus-message.c;h=d00455a1121de100b01e64cb5a61e6c550a47398;hp=323413406a4e278d062d99d678feb5155e54aeda;hb=f2322f0b64107b2eee1fadb6c59857381277a9f8;hpb=29804cc1e0f37ee34301530fd7f1eb8550be464e diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 323413406..d00455a11 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -28,6 +28,7 @@ #include "strv.h" #include "time-util.h" #include "cgroup-util.h" +#include "memfd.h" #include "sd-bus.h" #include "bus-message.h" @@ -70,7 +71,7 @@ static void message_free_part(sd_bus_message *m, struct bus_body_part *part) { if (part->mapped > 0) assert_se(munmap(part->data, part->mapped) == 0); - close_nointr_nofail(part->memfd); + safe_close(part->memfd); } } else if (part->munmap_this) @@ -136,8 +137,7 @@ static void message_free(sd_bus_message *m) { ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &off); } - if (m->bus) - sd_bus_unref(m->bus); + sd_bus_unref(m->bus); if (m->free_fds) { close_many(m->fds, m->n_fds); @@ -373,6 +373,7 @@ int bus_message_from_header( struct bus_header *h; size_t a, label_sz; + assert(bus); assert(buffer || length <= 0); assert(fds || n_fds <= 0); assert(ret); @@ -426,10 +427,9 @@ int bus_message_from_header( m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; } - if (bus) - m->bus = sd_bus_ref(bus); - + m->bus = sd_bus_ref(bus); *ret = m; + return 0; } @@ -489,6 +489,8 @@ fail: static sd_bus_message *message_new(sd_bus *bus, uint8_t type) { sd_bus_message *m; + assert(bus); + m = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header)); if (!m) return NULL; @@ -500,24 +502,23 @@ static sd_bus_message *message_new(sd_bus *bus, uint8_t type) { m->header->version = bus ? bus->message_version : 1; m->allow_fds = !bus || bus->can_fds || (bus->state != BUS_HELLO && bus->state != BUS_RUNNING); m->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(m); - - if (bus) - m->bus = sd_bus_ref(bus); + m->bus = sd_bus_ref(bus); return m; } _public_ int sd_bus_message_new_signal( sd_bus *bus, + sd_bus_message **m, const char *path, const char *interface, - const char *member, - sd_bus_message **m) { + const char *member) { sd_bus_message *t; int r; - assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN); + assert_return(bus, -ENOTCONN); + assert_return(bus->state != BUS_UNSET, -ENOTCONN); assert_return(object_path_is_valid(path), -EINVAL); assert_return(interface_name_is_valid(interface), -EINVAL); assert_return(member_name_is_valid(member), -EINVAL); @@ -549,16 +550,17 @@ fail: _public_ int sd_bus_message_new_method_call( sd_bus *bus, + sd_bus_message **m, const char *destination, const char *path, const char *interface, - const char *member, - sd_bus_message **m) { + const char *member) { sd_bus_message *t; int r; - assert_return(!bus || bus->state != BUS_UNSET, -ENOTCONN); + assert_return(bus, -ENOTCONN); + assert_return(bus->state != BUS_UNSET, -ENOTCONN); assert_return(!destination || service_name_is_valid(destination), -EINVAL); assert_return(object_path_is_valid(path), -EINVAL); assert_return(!interface || interface_name_is_valid(interface), -EINVAL); @@ -607,7 +609,7 @@ static int message_new_reply( assert_return(call, -EINVAL); assert_return(call->sealed, -EPERM); assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL); - assert_return(!call->bus || call->bus->state != BUS_UNSET, -ENOTCONN); + assert_return(call->bus->state != BUS_UNSET, -ENOTCONN); assert_return(m, -EINVAL); t = message_new(call->bus, type); @@ -617,7 +619,7 @@ static int message_new_reply( t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_cookie = BUS_MESSAGE_COOKIE(call); - r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie); + r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie); if (r < 0) goto fail; @@ -647,8 +649,8 @@ _public_ int sd_bus_message_new_method_return( _public_ int sd_bus_message_new_method_error( sd_bus_message *call, - const sd_bus_error *e, - sd_bus_message **m) { + sd_bus_message **m, + const sd_bus_error *e) { sd_bus_message *t; int r; @@ -697,23 +699,23 @@ _public_ int sd_bus_message_new_method_errorf( bus_error_setfv(&error, name, format, ap); va_end(ap); - return sd_bus_message_new_method_error(call, &error, m); + return sd_bus_message_new_method_error(call, m, &error); } _public_ int sd_bus_message_new_method_errno( sd_bus_message *call, + sd_bus_message **m, int error, - const sd_bus_error *p, - sd_bus_message **m) { + const sd_bus_error *p) { _cleanup_free_ sd_bus_error berror = SD_BUS_ERROR_NULL; if (sd_bus_error_is_set(p)) - return sd_bus_message_new_method_error(call, p, m); + return sd_bus_message_new_method_error(call, m, p); sd_bus_error_set_errno(&berror, error); - return sd_bus_message_new_method_error(call, &berror, m); + return sd_bus_message_new_method_error(call, m, &berror); } _public_ int sd_bus_message_new_method_errnof( @@ -730,7 +732,7 @@ _public_ int sd_bus_message_new_method_errnof( bus_error_set_errnofv(&berror, error, format, ap); va_end(ap); - return sd_bus_message_new_method_error(call, &berror, m); + return sd_bus_message_new_method_error(call, m, &berror); } int bus_message_new_synthetic_error( @@ -742,6 +744,7 @@ int bus_message_new_synthetic_error( sd_bus_message *t; int r; + assert(bus); assert(sd_bus_error_is_set(e)); assert(m); @@ -752,7 +755,7 @@ int bus_message_new_synthetic_error( t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_cookie = cookie; - r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie); + r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie); if (r < 0) goto fail; @@ -799,9 +802,10 @@ _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) { assert(m->n_ref > 0); m->n_ref--; - if (m->n_ref <= 0) - message_free(m); + if (m->n_ref > 0) + return NULL; + message_free(m); return NULL; } @@ -1073,7 +1077,7 @@ static int part_make_space( uint64_t new_allocated; new_allocated = PAGE_ALIGN(sz > 0 ? 2 * sz : 1); - r = ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &new_allocated); + r = ftruncate(part->memfd, new_allocated); if (r < 0) { m->poisoned = true; return -errno; @@ -1274,7 +1278,7 @@ static int message_push_fd(sd_bus_message *m, int fd) { f = realloc(m->fds, sizeof(int) * (m->n_fds + 1)); if (!f) { m->poisoned = true; - close_nointr_nofail(copy); + safe_close(copy); return -ENOMEM; } @@ -1863,7 +1867,7 @@ _public_ int sd_bus_message_open_container( struct bus_container *c, *w; uint32_t *array_size = NULL; char *signature; - size_t before, begin; + size_t before, begin = 0; bool need_offsets = false; int r; @@ -2524,7 +2528,7 @@ _public_ int sd_bus_message_append_array_iovec( _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, char type, - sd_memfd *memfd) { + int memfd) { _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; ssize_t align, sz; @@ -2534,7 +2538,7 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, if (!m) return -EINVAL; - if (!memfd) + if (memfd < 0) return -EINVAL; if (m->sealed) return -EPERM; @@ -2543,15 +2547,15 @@ _public_ int sd_bus_message_append_array_memfd(sd_bus_message *m, if (m->poisoned) return -ESTALE; - r = sd_memfd_set_sealed(memfd, true); + r = memfd_set_sealed(memfd); if (r < 0) return r; - copy_fd = sd_memfd_dup_fd(memfd); + copy_fd = dup(memfd); if (copy_fd < 0) return copy_fd; - r = sd_memfd_get_size(memfd, &size); + r = memfd_get_size(memfd, &size); if (r < 0) return r; @@ -2590,7 +2594,7 @@ _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, sd_memfd *memfd) { +_public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, int memfd) { _cleanup_close_ int copy_fd = -1; struct bus_body_part *part; struct bus_container *c; @@ -2599,19 +2603,19 @@ _public_ int sd_bus_message_append_string_memfd(sd_bus_message *m, sd_memfd *mem int r; assert_return(m, -EINVAL); - assert_return(memfd, -EINVAL); + assert_return(memfd >= 0, -EINVAL); assert_return(!m->sealed, -EPERM); assert_return(!m->poisoned, -ESTALE); - r = sd_memfd_set_sealed(memfd, true); + r = memfd_set_sealed(memfd); if (r < 0) return r; - copy_fd = sd_memfd_dup_fd(memfd); + copy_fd = dup(memfd); if (copy_fd < 0) return copy_fd; - r = sd_memfd_get_size(memfd, &size); + r = memfd_get_size(memfd, &size); if (r < 0) return r; @@ -2784,7 +2788,7 @@ int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) { /* 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 && m->bus && m->bus->use_memfd) { + if (m->destination && 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; @@ -2796,11 +2800,11 @@ int bus_message_seal(sd_bus_message *m, uint64_t cookie, usec_t timeout) { /* Then, sync up real memfd size */ sz = part->size; - if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SIZE_SET, &sz) < 0) + if (ftruncate(part->memfd, sz) < 0) return -errno; /* Finally, try to seal */ - if (ioctl(part->memfd, KDBUS_CMD_MEMFD_SEAL_SET, 1) >= 0) + if (fcntl(part->memfd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE) >= 0) part->sealed = true; } } @@ -2837,7 +2841,7 @@ int bus_body_part_map(struct bus_body_part *part) { psz = PAGE_ALIGN(part->size); if (part->memfd >= 0) - p = mmap(NULL, psz, PROT_READ, MAP_SHARED, part->memfd, 0); + p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE, part->memfd, 0); else if (part->is_zero) p = mmap(NULL, psz, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); else @@ -4215,7 +4219,7 @@ static int message_read_ap( * in a single stackframe. We hence implement our own * home-grown stack in an array. */ - n_array = (unsigned) -1; /* lenght of current array entries */ + n_array = (unsigned) -1; /* length of current array entries */ n_struct = strlen(types); /* length of current struct contents signature */ for (;;) { @@ -4885,6 +4889,7 @@ int bus_message_parse_fields(sd_bus_message *m) { size_t ri; int r; uint32_t unix_fds = 0; + bool unix_fds_set = false; void *offsets = NULL; unsigned n_offsets = 0; size_t sz = 0; @@ -5044,7 +5049,7 @@ int bus_message_parse_fields(sd_bus_message *m) { r = message_peek_field_string(m, service_name_is_valid, &ri, item_size, &m->sender); - if (r >= 0 && m->sender[0] == ':' && m->bus && m->bus->bus_client && !m->bus->is_kernel) { + if (r >= 0 && m->sender[0] == ':' && m->bus->bus_client && !m->bus->is_kernel) { m->creds.unique_name = (char*) m->sender; m->creds.mask |= SD_BUS_CREDS_UNIQUE_NAME & m->bus->creds_mask; } @@ -5075,24 +5080,29 @@ int bus_message_parse_fields(sd_bus_message *m) { break; } - case BUS_MESSAGE_HEADER_REPLY_SERIAL: + case BUS_MESSAGE_HEADER_REPLY_SERIAL: { + uint32_t serial; + if (m->reply_cookie != 0) return -EBADMSG; if (!streq(signature, "u")) return -EBADMSG; - r = message_peek_field_uint32(m, &ri, item_size, &m->reply_cookie); + r = message_peek_field_uint32(m, &ri, item_size, &serial); if (r < 0) return r; + m->reply_cookie = serial; + if (m->reply_cookie == 0) return -EBADMSG; break; + } case BUS_MESSAGE_HEADER_UNIX_FDS: - if (unix_fds != 0) + if (unix_fds_set) return -EBADMSG; if (!streq(signature, "u")) @@ -5102,9 +5112,7 @@ int bus_message_parse_fields(sd_bus_message *m) { if (r < 0) return -EBADMSG; - if (unix_fds == 0) - return -EBADMSG; - + unix_fds_set = true; break; default: @@ -5468,14 +5476,14 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { switch ((*m)->header->type) { case SD_BUS_MESSAGE_SIGNAL: - r = sd_bus_message_new_signal(bus, (*m)->path, (*m)->interface, (*m)->member, &n); + r = sd_bus_message_new_signal(bus, &n, (*m)->path, (*m)->interface, (*m)->member); if (r < 0) return r; break; case SD_BUS_MESSAGE_METHOD_CALL: - r = sd_bus_message_new_method_call(bus, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member, &n); + r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member); if (r < 0) return r; @@ -5489,7 +5497,7 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { return -ENOMEM; n->reply_cookie = (*m)->reply_cookie; - r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_cookie); + r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie); if (r < 0) return r;