X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-message.c;h=8134d77f36fea46634f8308d2a0cf836af871445;hb=a5e4972c8956cecf35fa4780e1cfe7c378bfcba1;hp=fb4718085bb6a73288ba5b3b928686a6669c6389;hpb=2100fa1099b086411270a2876dde0532ea2806fa;p=elogind.git diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index fb4718085..8134d77f3 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -25,6 +25,8 @@ #include "util.h" #include "utf8.h" #include "strv.h" +#include "time-util.h" +#include "cgroup-util.h" #include "sd-bus.h" #include "bus-message.h" @@ -32,7 +34,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,15 +63,24 @@ 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); free(m->peeked_signature); + + free(m->unit); + free(m->user_unit); + free(m->session); free(m); } @@ -225,19 +235,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 +266,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) + ALIGN8(fs) + 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 +284,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) + ALIGN8(fs); m->fds = fds; m->n_fds = n_fds; @@ -295,15 +295,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; - r = message_parse_fields(m); + r = bus_message_parse_fields(m); if (r < 0) goto fail; @@ -634,8 +662,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; @@ -644,8 +674,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; @@ -654,8 +686,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; @@ -664,18 +698,199 @@ 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; + + *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; - return m->label; + *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_unit(sd_bus_message *m, const char **ret) { + int r; + + if (!m) + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->cgroup) + return -ESRCH; + + if (!m->unit) { + r = cg_path_get_unit(m->cgroup, &m->unit); + if (r < 0) + return r; + } + + *ret = m->unit; + return 0; +} + +int sd_bus_message_get_user_unit(sd_bus_message *m, const char **ret) { + int r; + + if (!m) + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->cgroup) + return -ESRCH; + + if (!m->user_unit) { + r = cg_path_get_user_unit(m->cgroup, &m->user_unit); + if (r < 0) + return r; + } + + *ret = m->user_unit; + return 0; +} + +int sd_bus_message_get_session(sd_bus_message *m, const char **ret) { + int r; + + if (!m) + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->cgroup) + return -ESRCH; + + if (!m->session) { + r = cg_path_get_session(m->cgroup, &m->session); + if (r < 0) + return r; + } + + *ret = m->session; + 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) { @@ -2600,7 +2815,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; @@ -2795,6 +3010,7 @@ static int message_parse_fields(sd_bus_message *m) { int bus_message_seal(sd_bus_message *m, uint64_t serial) { int r; + size_t l, a; assert(m); @@ -2817,6 +3033,22 @@ 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; @@ -2837,6 +3069,8 @@ int sd_bus_message_set_destination(sd_bus_message *m, const char *destination) { } int bus_message_dump(sd_bus_message *m) { + const char *u = NULL, *uu = NULL, *s = NULL; + char **cmdline = NULL; unsigned level = 1; int r; @@ -2881,6 +3115,55 @@ 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); + + sd_bus_message_get_unit(m, &u); + if (u) + printf("\tunit=[%s]\n", u); + sd_bus_message_get_user_unit(m, &uu); + if (uu) + printf("\tuser_unit=[%s]\n", uu); + sd_bus_message_get_session(m, &s); + if (s) + printf("\tsession=[%s]\n", s); + + 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)); @@ -3041,7 +3324,7 @@ int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) { assert(buffer); assert(sz); - total = bus_message_size(m); + total = BUS_MESSAGE_SIZE(m); p = malloc(total); if (!p) @@ -3100,8 +3383,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); @@ -3109,7 +3392,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; @@ -3122,23 +3407,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; } -size_t bus_message_size(sd_bus_message *m) { - assert(m); - assert(m->sealed); +int bus_header_size(struct bus_header *h, size_t *sum) { + size_t fs, bs; - return - sizeof(*m->header) + - ALIGN8(m->header->fields_size) + - m->header->body_size; + 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; }