X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-message.c;h=fdc3ac68136aa8dde199ea76a59ad748a9c95642;hb=f8e013f8bf476e6d61fb2e218c85e23032a46302;hp=8134d77f36fea46634f8308d2a0cf836af871445;hpb=d8d3d8a781031d6b1ee4e5f57ec21f16c20a4cf2;p=elogind.git diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index 8134d77f3..fdc3ac681 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -861,6 +861,17 @@ int sd_bus_message_get_session(sd_bus_message *m, const char **ret) { 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) { size_t n, i; const char *p; @@ -893,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; @@ -1155,6 +1207,60 @@ int sd_bus_message_append_basic(sd_bus_message *m, char type, const void *p) { return message_append_basic(m, type, p, NULL); } +int sd_bus_message_append_string_space(sd_bus_message *m, size_t size, char **s) { + struct bus_container *c; + char *e; + void *a; + int r; + + if (!m) + return -EINVAL; + if (!s) + return -EINVAL; + if (m->sealed) + return -EPERM; + + c = message_get_container(m); + + if (c->signature && c->signature[c->index]) { + /* Container signature is already set */ + + if (c->signature[c->index] != SD_BUS_TYPE_STRING) + return -ENXIO; + } else { + /* Maybe we can append to the signature? But only if this is the top-level container*/ + if (c->enclosing != 0) + return -ENXIO; + + e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRING), NULL); + if (!e) + return -ENOMEM; + } + + + a = message_extend_body(m, 4, 4 + size + 1); + if (!a) { + r = -ENOMEM; + goto fail; + } + + *(uint32_t*) a = size; + *s = (char*) a + 4; + + (*s)[size] = 0; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + return 0; + +fail: + if (e) + c->signature[c->index] = 0; + + return r; +} + static int bus_message_open_array( sd_bus_message *m, struct bus_container *c, @@ -1386,6 +1492,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) @@ -1407,6 +1514,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) @@ -1429,7 +1541,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; } @@ -1455,6 +1568,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; @@ -1710,6 +1853,68 @@ int sd_bus_message_append(sd_bus_message *m, const char *types, ...) { return r; } +int sd_bus_message_append_array_space(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_space(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; @@ -1938,7 +2143,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; } @@ -2134,6 +2339,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) @@ -2176,6 +2382,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) @@ -2198,6 +2407,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; @@ -2232,6 +2442,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; @@ -2575,6 +2807,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, @@ -3073,6 +3358,8 @@ int bus_message_dump(sd_bus_message *m) { char **cmdline = NULL; unsigned level = 1; int r; + uid_t owner, audit_loginuid; + uint32_t audit_sessionid; assert(m); @@ -3149,6 +3436,14 @@ int bus_message_dump(sd_bus_message *m) { 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;