X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-message.c;h=afd4551b4ef0cbf175c19716aa117c6cecfc09c6;hp=103e2c1f65629bb38c61b86994f0a51ab2db1bee;hb=b3af9646f8ac23e73fe1d7af3b69e35b1547b13e;hpb=42c5aaf3ba3eb9e11a1a2cad105e0dd956ac9763 diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 103e2c1f6..afd4551b4 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -26,6 +26,7 @@ #include "utf8.h" #include "strv.h" #include "time-util.h" +#include "cgroup-util.h" #include "sd-bus.h" #include "bus-message.h" @@ -76,6 +77,10 @@ static void message_free(sd_bus_message *m) { free(m->root_container.signature); free(m->peeked_signature); + + free(m->unit); + free(m->user_unit); + free(m->session); free(m); } @@ -657,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; @@ -667,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; @@ -677,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; @@ -687,8 +698,10 @@ 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; @@ -697,26 +710,32 @@ int sd_bus_message_get_tid(sd_bus_message *m, pid_t *tid) { int sd_bus_message_get_pid_starttime(sd_bus_message *m, uint64_t *usec) { if (!m) return -EINVAL; + if (!usec) + return -EINVAL; if (m->pid_starttime <= 0) - return -ENOENT; + return -ESRCH; *usec = m->pid_starttime; return 0; } -const char *sd_bus_message_get_selinux_context(sd_bus_message *m) { +int sd_bus_message_get_selinux_context(sd_bus_message *m, const char **ret) { if (!m) - return NULL; + return -EINVAL; + if (!m->label) + return -ESRCH; - return m->label; + *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 -ENOENT; + return -ESRCH; *usec = m->monotonic; return 0; @@ -725,33 +744,132 @@ int sd_bus_message_get_monotonic_timestamp(sd_bus_message *m, uint64_t *usec) { 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 -ENOENT; + return -ESRCH; *usec = m->realtime; return 0; } -const char *sd_bus_message_get_comm(sd_bus_message *m) { +int sd_bus_message_get_comm(sd_bus_message *m, const char **ret) { if (!m) - return NULL; + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->comm) + return -ESRCH; - return m->comm; + *ret = m->comm; + return 0; } -const char *sd_bus_message_get_tid_comm(sd_bus_message *m) { +int sd_bus_message_get_tid_comm(sd_bus_message *m, const char **ret) { if (!m) - return NULL; + return -EINVAL; + if (!ret) + return -EINVAL; + if (!m->tid_comm) + return -ESRCH; - return m->tid_comm; + *ret = m->tid_comm; + return 0; } -const char *sd_bus_message_get_exe(sd_bus_message *m) { +int sd_bus_message_get_exe(sd_bus_message *m, const char **ret) { if (!m) - return NULL; + 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; - return m->exe; + *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_owner_uid(sd_bus_message *m, uid_t *uid) { + if (!m) + return -EINVAL; + if (!uid) + return -EINVAL; + if (!m->cgroup) + return -ESRCH; + + return cg_path_get_owner_uid(m->cgroup, uid); } int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) { @@ -786,6 +904,47 @@ int sd_bus_message_get_cmdline(sd_bus_message *m, char ***cmdline) { return 0; } +int sd_bus_message_get_audit_sessionid(sd_bus_message *m, uint32_t *sessionid) { + if (!m) + return -EINVAL; + if (!sessionid) + return -EINVAL; + if (!m->audit) + return -ESRCH; + + *sessionid = m->audit->sessionid; + return 0; +} + +int sd_bus_message_get_audit_loginuid(sd_bus_message *m, uid_t *uid) { + if (!m) + return -EINVAL; + if (!uid) + return -EINVAL; + if (!m->audit) + return -ESRCH; + + *uid = m->audit->loginuid; + return 0; +} + +int sd_bus_message_has_effective_cap(sd_bus_message *m, int capability) { + unsigned sz; + + if (!m) + return -EINVAL; + if (capability < 0) + return -EINVAL; + if (!m->capability) + return -ESRCH; + + sz = m->capability_size / 4; + if ((unsigned) capability >= sz*8) + return 0; + + return !!(m->capability[2 * sz + (capability / 8)] & (1 << (capability % 8))); +} + int sd_bus_message_is_signal(sd_bus_message *m, const char *interface, const char *member) { if (!m) return -EINVAL; @@ -1279,6 +1438,7 @@ int sd_bus_message_open_container( struct bus_container *c, *w; uint32_t *array_size = NULL; char *signature; + size_t before; int r; if (!m) @@ -1300,6 +1460,11 @@ int sd_bus_message_open_container( if (!signature) return -ENOMEM; + /* Save old index in the parent container, in case we have to + * abort this container */ + c->saved_index = c->index; + before = m->header->body_size; + if (type == SD_BUS_TYPE_ARRAY) r = bus_message_open_array(m, c, contents, &array_size); else if (type == SD_BUS_TYPE_VARIANT) @@ -1322,7 +1487,8 @@ int sd_bus_message_open_container( w->signature = signature; w->index = 0; w->array_size = array_size; - w->begin = 0; + w->before = before; + w->begin = m->rindex; return 0; } @@ -1348,6 +1514,36 @@ int sd_bus_message_close_container(sd_bus_message *m) { return 0; } +static void message_abort_container(sd_bus_message *m) { + struct bus_container *c; + size_t delta; + + assert(m); + assert(!m->sealed); + assert(m->n_containers > 0); + + c = message_get_container(m); + + /* Undo appends */ + assert(m->header->body_size >= c->before); + delta = m->header->body_size - c->before; + m->header->body_size = c->before; + + /* Free container */ + free(c->signature); + m->n_containers--; + + /* Correct index of new top-level container */ + c = message_get_container(m); + c->index = c->saved_index; + + /* Correct array sizes all the way up */ + for (c = m->containers; c < m->containers + m->n_containers; c++) + if (c->array_size) { + assert(*c->array_size >= delta); + *c->array_size -= delta; + } +} typedef struct { const char *types; @@ -1603,6 +1799,68 @@ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) { return r; } +int sd_bus_message_append_array_ptr(sd_bus_message *m, char type, size_t size, void **ptr) { + ssize_t align, sz; + void *a; + int r; + + if (!m) + return -EINVAL; + if (m->sealed) + return -EPERM; + if (!bus_type_is_trivial(type)) + return -EINVAL; + if (!ptr && size > 0) + return -EINVAL; + + align = bus_type_get_alignment(type); + sz = bus_type_get_size(type); + + assert_se(align > 0); + assert_se(sz > 0); + + if (size % sz != 0) + return -EINVAL; + + r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); + if (r < 0) + return r; + + a = message_extend_body(m, align, size); + if (!a) { + r = -ENOMEM; + goto fail; + } + + r = sd_bus_message_close_container(m); + if (r < 0) + goto fail; + + *ptr = a; + return 0; + +fail: + message_abort_container(m); + return r; +} + +int sd_bus_message_append_array(sd_bus_message *m, char type, const void *ptr, size_t size) { + int r; + void *p; + + if (!ptr && size > 0) + return -EINVAL; + + r = sd_bus_message_append_array_ptr(m, type, size, &p); + if (r < 0) + return r; + + if (size > 0) + memcpy(p, ptr, size); + + return 0; +} + static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) { size_t k, start, n; @@ -1831,7 +2089,7 @@ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { assert_not_reached("Unknown basic type..."); } - m->rindex = rindex; + m->rindex = rindex; break; } @@ -2027,6 +2285,7 @@ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *con struct bus_container *c, *w; uint32_t *array_size = NULL; char *signature; + size_t before; int r; if (!m) @@ -2069,6 +2328,9 @@ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *con if (!signature) return -ENOMEM; + c->saved_index = c->index; + before = m->rindex; + if (type == SD_BUS_TYPE_ARRAY) r = bus_message_enter_array(m, c, contents, &array_size); else if (type == SD_BUS_TYPE_VARIANT) @@ -2091,6 +2353,7 @@ int sd_bus_message_enter_container(sd_bus_message *m, char type, const char *con w->signature = signature; w->index = 0; w->array_size = array_size; + w->before = before; w->begin = m->rindex; return 1; @@ -2125,6 +2388,28 @@ int sd_bus_message_exit_container(sd_bus_message *m) { return 1; } +static void message_quit_container(sd_bus_message *m) { + struct bus_container *c; + + assert(m); + assert(m->sealed); + assert(m->n_containers > 0); + + c = message_get_container(m); + + /* Undo seeks */ + assert(m->rindex >= c->before); + m->rindex = c->before; + + /* Free container */ + free(c->signature); + m->n_containers--; + + /* Correct index of new top-level container */ + c = message_get_container(m); + c->index = c->saved_index; +} + int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char **contents) { struct bus_container *c; int r; @@ -2468,6 +2753,59 @@ int sd_bus_message_read(sd_bus_message *m, const char *types, ...) { return r; } +int sd_bus_message_read_array(sd_bus_message *m, char type, const void **ptr, size_t *size) { + struct bus_container *c; + void *p; + size_t sz; + ssize_t align; + int r; + + if (!m) + return -EINVAL; + if (!m->sealed) + return -EPERM; + if (!bus_type_is_trivial(type)) + return -EINVAL; + if (!ptr) + return -EINVAL; + if (!size) + return -EINVAL; + if (BUS_MESSAGE_NEED_BSWAP(m)) + return -ENOTSUP; + + align = bus_type_get_alignment(type); + if (align < 0) + return align; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, CHAR_TO_STR(type)); + if (r < 0) + return r; + + c = message_get_container(m); + sz = BUS_MESSAGE_BSWAP32(m, *c->array_size); + + r = message_peek_body(m, &m->rindex, align, sz, &p); + if (r < 0) + goto fail; + if (r == 0) { + r = -EBADMSG; + goto fail; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + goto fail; + + *ptr = (const void*) p; + *size = sz; + + return 1; + +fail: + message_quit_container(m); + return r; +} + static int message_peek_fields( sd_bus_message *m, size_t *rindex, @@ -2962,9 +3300,12 @@ 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; + uid_t owner, audit_loginuid; + uint32_t audit_sessionid; assert(m); @@ -3029,6 +3370,26 @@ int bus_message_dump(sd_bus_message *m) { 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_owner_uid(m, &owner) >= 0) + printf("\towner_uid=%lu\n", (unsigned long) owner); + if (sd_bus_message_get_audit_loginuid(m, &audit_loginuid) >= 0) + printf("\taudit_loginuid=%lu\n", (unsigned long) audit_loginuid); + if (sd_bus_message_get_audit_sessionid(m, &audit_sessionid) >= 0) + printf("\taudit_sessionid=%lu\n", (unsigned long) audit_sessionid); + + printf("\tCAP_KILL=%i\n", sd_bus_message_has_effective_cap(m, 5)); if (sd_bus_message_get_cmdline(m, &cmdline) >= 0) { char **c;