X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-message.c;h=a22962559de8ed94c298443981c938e70da536ed;hb=6693860fab7e34ffc59a748d3064d553fba25f2c;hp=a1bae4d1a76d75d467028c35e83f76eb19dfc893;hpb=80a46c7313b8fc4682881cb3a2ca9e4d743fcb2b;p=elogind.git diff --git a/src/libsystemd-bus/bus-message.c b/src/libsystemd-bus/bus-message.c index a1bae4d1a..a22962559 100644 --- a/src/libsystemd-bus/bus-message.c +++ b/src/libsystemd-bus/bus-message.c @@ -23,6 +23,7 @@ #include "util.h" #include "utf8.h" +#include "strv.h" #include "sd-bus.h" #include "bus-message.h" @@ -322,6 +323,8 @@ int sd_bus_message_new_signal( if (!t) return -ENOMEM; + t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED; + r = message_append_field_string(t, SD_BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path); if (r < 0) goto fail; @@ -400,6 +403,8 @@ static int message_new_reply( if (!call) return -EINVAL; + if (!call->sealed) + return -EPERM; if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL) return -EINVAL; if (!m) @@ -409,6 +414,7 @@ static int message_new_reply( if (!t) return -ENOMEM; + t->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_serial = BUS_MESSAGE_SERIAL(call); r = message_append_field_uint32(t, SD_BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_serial); @@ -424,6 +430,7 @@ static int message_new_reply( t->dont_send = !!(call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED); *m = t; + return 0; fail: message_free(t); @@ -447,9 +454,7 @@ int sd_bus_message_new_method_error( sd_bus_message *t; int r; - if (!e) - return -EINVAL; - if (!e->name) + if (!sd_bus_error_is_set(e)) return -EINVAL; if (!m) return -EINVAL; @@ -763,11 +768,27 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void case SD_BUS_TYPE_STRING: case SD_BUS_TYPE_OBJECT_PATH: + + if (!p) { + if (e) + c->signature[c->index] = 0; + + return -EINVAL; + } + align = 4; sz = 4 + strlen(p) + 1; break; case SD_BUS_TYPE_SIGNATURE: + + if (!p) { + if (e) + c->signature[c->index] = 0; + + return -EINVAL; + } + align = 1; sz = 1 + strlen(p) + 1; break; @@ -1353,8 +1374,7 @@ static int message_peek_body(sd_bus_message *m, size_t *rindex, size_t align, si return buffer_peek(m->body, BUS_MESSAGE_BODY_SIZE(m), rindex, align, nbytes, ret); } -static bool validate_string(const char *s, size_t l) { - assert(s); +static bool validate_nul(const char *s, size_t l) { /* Check for NUL chars in the string */ if (memchr(s, 0, l)) @@ -1364,6 +1384,14 @@ static bool validate_string(const char *s, size_t l) { if (s[l] != 0) return false; + return true; +} + +static bool validate_string(const char *s, size_t l) { + + if (!validate_nul(s, l)) + return false; + /* Check if valid UTF8 */ if (!utf8_is_valid(s)) return false; @@ -1372,12 +1400,8 @@ static bool validate_string(const char *s, size_t l) { } static bool validate_signature(const char *s, size_t l) { - /* Check for NUL chars in the signature */ - if (memchr(s, 0, l)) - return false; - /* Check for NUL termination */ - if (s[l] != 0) + if (!validate_nul(s, l)) return false; /* Check if valid signature */ @@ -1387,6 +1411,17 @@ static bool validate_signature(const char *s, size_t l) { return true; } +static bool validate_object_path(const char *s, size_t l) { + + if (!validate_nul(s, l)) + return false; + + if (!object_path_is_valid(s)) + return false; + + return true; +} + int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { struct bus_container *c; int r; @@ -1426,8 +1461,13 @@ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { if (r == 0) return -EBADMSG; - if (!validate_string(q, l)) - return -EBADMSG; + if (type == SD_BUS_TYPE_OBJECT_PATH) { + if (!validate_object_path(q, l)) + return -EBADMSG; + } else { + if (!validate_string(q, l)) + return -EBADMSG; + } m->rindex = rindex; *(const char**) p = q; @@ -1544,7 +1584,7 @@ static int bus_message_enter_array( if (r <= 0) return r; - if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > 67108864) + if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE) return -EBADMSG; r = message_peek_body(m, &rindex, alignment, 0, NULL); @@ -1893,7 +1933,7 @@ eof: return 0; } -int sd_bus_message_rewind(sd_bus_message *m, bool complete) { +int sd_bus_message_rewind(sd_bus_message *m, int complete) { struct bus_container *c; if (!m) @@ -2083,6 +2123,7 @@ static int message_peek_fields( static int message_peek_field_string( sd_bus_message *m, + bool (*validate)(const char *p), size_t *ri, const char **ret) { @@ -2102,8 +2143,16 @@ static int message_peek_field_string( if (r < 0) return r; - if (!validate_string(q, l)) - return -EBADMSG; + if (validate) { + if (!validate_nul(q, l)) + return -EBADMSG; + + if (!validate(q)) + return -EBADMSG; + } else { + if (!validate_string(q, l)) + return -EBADMSG; + } if (ret) *ret = q; @@ -2190,10 +2239,17 @@ static int message_skip_fields( if (!t) return 0; - if (t == SD_BUS_TYPE_STRING || - t == SD_BUS_TYPE_OBJECT_PATH) { + if (t == SD_BUS_TYPE_STRING) { + + r = message_peek_field_string(m, NULL, ri, NULL); + if (r < 0) + return r; + + (*signature)++; + + } else if (t == SD_BUS_TYPE_OBJECT_PATH) { - r = message_peek_field_string(m, ri, NULL); + r = message_peek_field_string(m, object_path_is_valid, ri, NULL); if (r < 0) return r; @@ -2210,8 +2266,8 @@ static int message_skip_fields( } else if (bus_type_is_basic(t)) { size_t align, k; - align = bus_type_get_alignment(align); - k = bus_type_get_size(align); + align = bus_type_get_alignment(t); + k = bus_type_get_size(t); r = message_peek_fields(m, ri, align, k, NULL); if (r < 0) @@ -2243,7 +2299,7 @@ static int message_skip_fields( return r; nas = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); - if (nas > 67108864) + if (nas > BUS_ARRAY_MAX_SIZE) return -EBADMSG; r = message_peek_fields(m, ri, alignment, 0, NULL); @@ -2320,42 +2376,42 @@ static int message_parse_fields(sd_bus_message *m) { if (!streq(signature, "o")) return -EBADMSG; - r = message_peek_field_string(m, &ri, &m->path); + r = message_peek_field_string(m, object_path_is_valid, &ri, &m->path); break; case SD_BUS_MESSAGE_HEADER_INTERFACE: if (!streq(signature, "s")) return -EBADMSG; - r = message_peek_field_string(m, &ri, &m->interface); + r = message_peek_field_string(m, interface_name_is_valid, &ri, &m->interface); break; case SD_BUS_MESSAGE_HEADER_MEMBER: if (!streq(signature, "s")) return -EBADMSG; - r = message_peek_field_string(m, &ri, &m->member); + r = message_peek_field_string(m, member_name_is_valid, &ri, &m->member); break; case SD_BUS_MESSAGE_HEADER_ERROR_NAME: if (!streq(signature, "s")) return -EBADMSG; - r = message_peek_field_string(m, &ri, &m->error.name); + r = message_peek_field_string(m, error_name_is_valid, &ri, &m->error.name); break; case SD_BUS_MESSAGE_HEADER_DESTINATION: if (!streq(signature, "s")) return -EBADMSG; - r = message_peek_field_string(m, &ri, &m->destination); + r = message_peek_field_string(m, service_name_is_valid, &ri, &m->destination); break; case SD_BUS_MESSAGE_HEADER_SENDER: if (!streq(signature, "s")) return -EBADMSG; - r = message_peek_field_string(m, &ri, &m->sender); + r = message_peek_field_string(m, service_name_is_valid, &ri, &m->sender); break; @@ -2386,6 +2442,12 @@ static int message_parse_fields(sd_bus_message *m) { return -EBADMSG; r = message_peek_field_uint32(m, &ri, &m->reply_serial); + if (r < 0) + return r; + + if (m->reply_serial == 0) + return -EBADMSG; + break; default: @@ -2426,6 +2488,10 @@ static int message_parse_fields(sd_bus_message *m) { break; } + /* Try to read the error message, but if we can't it's a non-issue */ + if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) + sd_bus_message_read(m, "s", &m->error.message); + return 0; } @@ -2434,14 +2500,17 @@ static void setup_iovec(sd_bus_message *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) { @@ -2449,6 +2518,7 @@ static void setup_iovec(sd_bus_message *m) { 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++; } } @@ -2456,6 +2526,7 @@ static void setup_iovec(sd_bus_message *m) { 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++; } } @@ -2726,3 +2797,34 @@ int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz) { return 0; } + +int bus_message_read_strv_extend(sd_bus_message *m, char ***l) { + int r; + + assert(m); + assert(l); + + r = sd_bus_message_enter_container(m, 'a', "s"); + if (r < 0) + return r; + + for (;;) { + const char *s; + + r = sd_bus_message_read_basic(m, 's', &s); + if (r < 0) + return r; + if (r == 0) + break; + + r = strv_extend(l, s); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + return 0; +}