X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-message.c;h=b78d34bf7aaaf778b9a81110c7e8607fa5e40fb6;hb=4a875b6133c9ef0e984547f7ce3b09356be4f7bc;hp=3081664091af23e6629793efe057f1a00c644ff1;hpb=1ef2af5ae02aede39262dedd9fd358b607450662;p=elogind.git diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 308166409..b78d34bf7 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -25,6 +25,7 @@ #include "util.h" #include "utf8.h" #include "strv.h" +#include "time-util.h" #include "sd-bus.h" #include "bus-message.h" @@ -32,7 +33,6 @@ #include "bus-type.h" #include "bus-signature.h" -static int message_parse_fields(sd_bus_message *m); static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored); static void reset_containers(sd_bus_message *m) { @@ -62,11 +62,16 @@ static void message_free(sd_bus_message *m) { if (m->free_body) free(m->body); + if (m->free_kdbus) + free(m->kdbus); + if (m->free_fds) { close_many(m->fds, m->n_fds); free(m->fds); } + free(m->cmdline_array); + reset_containers(m); free(m->root_container.signature); @@ -225,19 +230,19 @@ static int message_append_field_uint32(sd_bus_message *m, uint8_t h, uint32_t x) return 0; } -int bus_message_from_malloc( +int bus_message_from_header( void *buffer, size_t length, int *fds, unsigned n_fds, const struct ucred *ucred, const char *label, + size_t extra, sd_bus_message **ret) { sd_bus_message *m; struct bus_header *h; - size_t total, fs, bs, label_sz, a; - int r; + size_t a, label_sz; assert(buffer || length <= 0); assert(fds || n_fds <= 0); @@ -256,24 +261,16 @@ int bus_message_from_malloc( if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID) return -EBADMSG; - if (h->endian == SD_BUS_NATIVE_ENDIAN) { - fs = h->fields_size; - bs = h->body_size; - } else if (h->endian == SD_BUS_REVERSE_ENDIAN) { - fs = bswap_32(h->fields_size); - bs = bswap_32(h->body_size); - } else + if (h->endian != SD_BUS_LITTLE_ENDIAN && + h->endian != SD_BUS_BIG_ENDIAN) return -EBADMSG; - total = sizeof(struct bus_header) + ALIGN_TO(fs, 8) + bs; - if (length != total) - return -EBADMSG; + a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); if (label) { label_sz = strlen(label); - a = ALIGN(sizeof(sd_bus_message)) + label_sz + 1; - } else - a = sizeof(sd_bus_message); + a += label_sz + 1; + } m = malloc0(a); if (!m) @@ -282,8 +279,6 @@ int bus_message_from_malloc( m->n_ref = 1; m->sealed = true; m->header = h; - m->fields = (uint8_t*) buffer + sizeof(struct bus_header); - m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN_TO(fs, 8); m->fds = fds; m->n_fds = n_fds; @@ -295,16 +290,43 @@ int bus_message_from_malloc( } if (label) { - m->label = (char*) m + ALIGN(sizeof(sd_bus_message)); + m->label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); memcpy(m->label, label, label_sz + 1); } + *ret = m; + return 0; +} + +int bus_message_from_malloc( + void *buffer, + size_t length, + int *fds, + unsigned n_fds, + const struct ucred *ucred, + const char *label, + sd_bus_message **ret) { + + sd_bus_message *m; + int r; + + r = bus_message_from_header(buffer, length, fds, n_fds, ucred, label, 0, &m); + if (r < 0) + return r; + + if (length != BUS_MESSAGE_SIZE(m)) { + r = -EBADMSG; + goto fail; + } + + m->fields = (uint8_t*) buffer + sizeof(struct bus_header); + m->body = (uint8_t*) buffer + sizeof(struct bus_header) + ALIGN8(BUS_MESSAGE_FIELDS_SIZE(m)); + m->n_iovec = 1; m->iovec[0].iov_base = buffer; m->iovec[0].iov_len = length; - m->size = length; - r = message_parse_fields(m); + r = bus_message_parse_fields(m); if (r < 0) goto fail; @@ -635,8 +657,10 @@ const sd_bus_error *sd_bus_message_get_error(sd_bus_message *m) { int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) { if (!m) return -EINVAL; + if (!uid) + return -EINVAL; if (!m->uid_valid) - return -ENOENT; + return -ESRCH; *uid = m->uid; return 0; @@ -645,8 +669,10 @@ int sd_bus_message_get_uid(sd_bus_message *m, uid_t *uid) { int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) { if (!m) return -EINVAL; + if (!gid) + return -EINVAL; if (!m->gid_valid) - return -ENOENT; + return -ESRCH; *gid = m->gid; return 0; @@ -655,8 +681,10 @@ int sd_bus_message_get_gid(sd_bus_message *m, gid_t *gid) { int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) { if (!m) return -EINVAL; + if (!pid) + return -EINVAL; if (m->pid <= 0) - return -ENOENT; + return -ESRCH; *pid = m->pid; return 0; @@ -665,18 +693,139 @@ int sd_bus_message_get_pid(sd_bus_message *m, pid_t *pid) { int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) { if (!m) return -EINVAL; + if (!tid) + return -EINVAL; if (m->tid <= 0) - return -ENOENT; + return -ESRCH; *tid = m->tid; return 0; } -const char *sd_bus_message_get_label(sd_bus_message *m) { +int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) { if (!m) - return NULL; + return -EINVAL; + if (!usec) + return -EINVAL; + if (m->pid_starttime <= 0) + return -ESRCH; - return m->label; + *usec = m->pid_starttime; + return 0; +} + +int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) { + if (!m) + return -EINVAL; + if (!m->label) + return -ESRCH; + + *ret = m->label; + return 0; +} + +int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) { + if (!m) + return -EINVAL; + if (!usec) + return -EINVAL; + if (m->monotonic <= 0) + return -ESRCH; + + *usec = m->monotonic; + return 0; +} + +int sd_bus_message_get_realtime_timestamp(sd_bus_message *m, uint64_t *usec) { + if (!m) + return -EINVAL; + if (!usec) + return -EINVAL; + if (m->realtime <= 0) + return -ESRCH; + + *usec = m->realtime; + return 0; +} + +int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) { + if (!m) + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->comm) + return -ESRCH; + + *ret = m->comm; + return 0; +} + +int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) { + if (!m) + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->tid_comm) + return -ESRCH; + + *ret = m->tid_comm; + return 0; +} + +int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) { + if (!m) + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->exe) + return -ESRCH; + + *ret = m->exe; + return 0; +} + +int sd_bus_message_get_cgroup(sd_bus_message *m, const char **ret) { + if (!m) + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->cgroup) + return -ESRCH; + + *ret = m->cgroup; + return 0; +} + +int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) { + size_t n, i; + const char *p; + bool first; + + if (!m) + return -EINVAL; + + if (!m->cmdline) + return -ENOENT; + + for (p = m->cmdline, n = 0; p < m->cmdline + m->cmdline_length; p++) + if (*p == 0) + n++; + + m->cmdline_array = new(char*, n + 1); + if (!m->cmdline_array) + return -ENOMEM; + + for (p = m->cmdline, i = 0, first = true; p < m->cmdline + m->cmdline_length; p++) { + if (first) + m->cmdline_array[i++] = (char*) p; + + first = *p == 0; + } + + m->cmdline_array[i] = NULL; + *cmdline = m->cmdline_array; + + return 0; } int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) { @@ -2601,7 +2750,7 @@ static int message_skip_fields( } } -static int message_parse_fields(sd_bus_message *m) { +int bus_message_parse_fields(sd_bus_message *m) { size_t ri; int r; uint32_t unix_fds = 0; @@ -2794,44 +2943,9 @@ static int message_parse_fields(sd_bus_message *m) { return 0; } -static void setup_iovec(sd_bus_message *m) { - assert(m); - assert(m->sealed); - - m->n_iovec = 0; - m->size = 0; - - m->iovec[m->n_iovec].iov_base = m->header; - m->iovec[m->n_iovec].iov_len = sizeof(*m->header); - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - - if (m->fields) { - m->iovec[m->n_iovec].iov_base = m->fields; - m->iovec[m->n_iovec].iov_len = m->header->fields_size; - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - - if (m->header->fields_size % 8 != 0) { - static const uint8_t padding[7] = { 0, 0, 0, 0, 0, 0, 0 }; - - m->iovec[m->n_iovec].iov_base = (void*) padding; - m->iovec[m->n_iovec].iov_len = 8 - m->header->fields_size % 8; - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - } - } - - if (m->body) { - m->iovec[m->n_iovec].iov_base = m->body; - m->iovec[m->n_iovec].iov_len = m->header->body_size; - m->size += m->iovec[m->n_iovec].iov_len; - m->n_iovec++; - } -} - int bus_message_seal(sd_bus_message *m, uint64_t serial) { int r; + size_t l, a; assert(m); @@ -2854,11 +2968,25 @@ int bus_message_seal(sd_bus_message *m, uint64_t serial) { return r; } + l = BUS_MESSAGE_FIELDS_SIZE(m); + a = ALIGN8(l) - l; + + if (a > 0) { + /* Add padding at the end, since we know the body + * needs to start at an 8 byte alignment. */ + void *p; + + p = message_extend_fields(m, 1, a); + if (!p) + return -ENOMEM; + + memset(p, 0, a); + m->header->fields_size -= a; + } + m->header->serial = serial; m->sealed = true; - setup_iovec(m); - return 0; } @@ -2876,6 +3004,7 @@ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) { } int bus_message_dump(sd_bus_message *m) { + char **cmdline = NULL; unsigned level = 1; int r; @@ -2920,6 +3049,45 @@ int bus_message_dump(sd_bus_message *m) { strna(m->error.message), yes_no(m->sealed)); + if (m->pid != 0) + printf("\tpid=%lu\n", (unsigned long) m->pid); + if (m->tid != 0) + printf("\ttid=%lu\n", (unsigned long) m->tid); + if (m->uid_valid) + printf("\tuid=%lu\n", (unsigned long) m->uid); + if (m->gid_valid) + printf("\tgid=%lu\n", (unsigned long) m->gid); + if (m->pid_starttime != 0) + printf("\tpid_starttime=%llu\n", (unsigned long long) m->pid_starttime); + if (m->monotonic != 0) + printf("\tmonotonic=%llu\n", (unsigned long long) m->monotonic); + if (m->realtime != 0) + printf("\trealtime=%llu\n", (unsigned long long) m->realtime); + if (m->exe) + printf("\texe=[%s]\n", m->exe); + if (m->comm) + printf("\tcomm=[%s]\n", m->comm); + if (m->tid_comm) + printf("\ttid_comm=[%s]\n", m->tid_comm); + if (m->label) + printf("\tlabel=[%s]\n", m->label); + if (m->cgroup) + printf("\tcgroup=[%s]\n", m->cgroup); + + if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) { + char **c; + + fputs("\tcmdline=[", stdout); + STRV_FOREACH(c, cmdline) { + if (c != cmdline) + putchar(' '); + + fputs(*c, stdout); + } + + fputs("]\n", stdout); + } + r = sd_bus_message_rewind(m, true); if (r < 0) { log_error("Failed to rewind: %s", strerror(-r)); @@ -3074,22 +3242,31 @@ int bus_message_dump(sd_bus_message *m) { int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) { size_t total; - unsigned i; void *p, *e; assert(m); assert(buffer); assert(sz); - for (i = 0, total = 0; i < m->n_iovec; i++) - total += m->iovec[i].iov_len; + total = BUS_MESSAGE_SIZE(m); p = malloc(total); if (!p) return -ENOMEM; - for (i = 0, e = p; i < m->n_iovec; i++) - e = mempcpy(e, m->iovec[i].iov_base, m->iovec[i].iov_len); + e = mempcpy(p, m->header, sizeof(*m->header)); + + if (m->fields) { + e = mempcpy(e, m->fields, m->header->fields_size); + + if (m->header->fields_size % 8 != 0) + e = mempset(e, 0, 8 - (m->header->fields_size % 8)); + } + + if (m->body) + e = mempcpy(e, m->body, m->header->body_size); + + assert(total == (size_t) ((uint8_t*) e - (uint8_t*) p)); *buffer = p; *sz = total; @@ -3130,8 +3307,8 @@ int bus_message_read_strv_extend(sd_bus_message *m, char ***l) { const char* bus_message_get_arg(sd_bus_message *m, unsigned i) { int r; - const char *t; - char type; + const char *t = NULL; + unsigned j; assert(m); @@ -3139,7 +3316,9 @@ const char* bus_message_get_arg(sd_bus_message *m, unsigned i) { if (r < 0) return NULL; - while (i > 0) { + for (j = 0; j <= i; j++) { + char type; + r = sd_bus_message_peek_type(m, &type, NULL); if (r < 0) return NULL; @@ -3152,13 +3331,26 @@ const char* bus_message_get_arg(sd_bus_message *m, unsigned i) { r = sd_bus_message_read_basic(m, type, &t); if (r < 0) return NULL; - - i--; } - r = sd_bus_message_rewind(m, true); - if (r < 0) - return NULL; - return t; } + +int bus_header_size(struct bus_header *h, size_t *sum) { + size_t fs, bs; + + assert(h); + assert(sum); + + if (h->endian == SD_BUS_NATIVE_ENDIAN) { + fs = h->fields_size; + bs = h->body_size; + } else if (h->endian == SD_BUS_REVERSE_ENDIAN) { + fs = bswap_32(h->fields_size); + bs = bswap_32(h->body_size); + } else + return -EBADMSG; + + *sum = sizeof(struct bus_header) + ALIGN8(fs) + bs; + return 0; +}