bus-message.c revision 022fb8558e797483709ab3e9fe846f04f7026dac
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering This file is part of systemd.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering Copyright 2013 Lennart Poettering
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering systemd is free software; you can redistribute it and/or modify it
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering under the terms of the GNU Lesser General Public License as published by
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering (at your option) any later version.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering systemd is distributed in the hope that it will be useful, but
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering Lesser General Public License for more details.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering You should have received a copy of the GNU Lesser General Public License
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringstatic int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringstatic void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return (void*) p;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return (void*) p;
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger if ((uint8_t*) p >= (uint8_t*) old_base + sz)
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger return (void*) p;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburgerstatic void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger /* If we can reuse the memfd, try that. For that it
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger * can't be sealed yet. */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
b85e1c2534ca3b396c2aaa7de384995b42d12e1bFilipe Brandenburger assert_se(munmap(part->data, part->mapped) == 0);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringstatic void message_reset_parts(sd_bus_message *m) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering while (m->n_body_parts > 0) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringstatic void message_reset_containers(sd_bus_message *m) {
3ff13c298d6d53293680c383768c3054fb9fcc30Filipe Brandenburger for (i = 0; i < m->n_containers; i++) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering m->n_containers = m->containers_allocated = 0;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringstatic void message_free(sd_bus_message *m) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering cmd_free.offset = (uint8_t *)m->kdbus - (uint8_t *)m->bus->kdbus_buffer;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering (void) ioctl(m->bus->input_fd, KDBUS_CMD_FREE, &cmd_free);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering free(m->root_container.peeked_signature);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poetteringstatic void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering old_size = sizeof(struct bus_header) + m->header->fields_size;
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering np = realloc(m->header, ALIGN8(new_size));
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Initially, the header is allocated as part of of
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * the sd_bus_message itself, let's replace it by
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * dynamic data */
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering memcpy(np, m->header, sizeof(struct bus_header));
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Zero out padding */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering memzero((uint8_t*) np + old_size, start - old_size);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering m->header->fields_size = new_size - sizeof(struct bus_header);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering /* Adjust quick access pointers */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering m->path = adjust_pointer(m->path, op, old_size, m->header);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering m->interface = adjust_pointer(m->interface, op, old_size, m->header);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering m->member = adjust_pointer(m->member, op, old_size, m->header);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering m->destination = adjust_pointer(m->destination, op, old_size, m->header);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering m->sender = adjust_pointer(m->sender, op, old_size, m->header);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering m->error.name = adjust_pointer(m->error.name, op, old_size, m->header);
dea7b6b043f0cd9e34ee719b9b612c3a4776387eLennart Poettering if (m->n_header_offsets >= ELEMENTSOF(m->header_offsets))
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering m->header_offsets[m->n_header_offsets++] = new_size - sizeof(struct bus_header);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char *s,
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering const char **ret) {
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* dbus1 doesn't allow strings over 32bit, let's enforce this
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering * globally, to not risk convertability */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* Signature "(yv)" where the variant contains "s" */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* (field id byte + 7x padding, ((string + NUL) + NUL + signature string 's') */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering p = message_extend_fields(m, 8, 1 + 7 + l + 1 + 1 + 1, true);
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */
84ac7bea360cd369df26910e9685a7eed2327088Lennart Poettering p = message_extend_fields(m, 8, 4 + 4 + l + 1, false);
if (ret)
static int message_append_field_signature(
sd_bus_message *m,
uint8_t h,
const char **ret) {
size_t l;
uint8_t *p;
assert(m);
l = strlen(s);
return -EINVAL;
if (BUS_MESSAGE_IS_GVARIANT(m))
return -ENOMEM;
if (ret)
uint8_t *p;
assert(m);
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -ENOMEM;
return -ENOMEM;
void *buffer,
int *fds,
unsigned n_fds,
const char *label,
sd_bus_message *m;
struct bus_header *h;
return -EBADMSG;
h = buffer;
return -EBADMSG;
if (h->serial == 0)
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
if (label) {
m = malloc0(a);
return -ENOMEM;
m->sealed = true;
m->header = h;
if (ucred) {
if (label) {
*ret = m;
void *buffer,
int *fds,
unsigned n_fds,
const char *label,
sd_bus_message *m;
r = -EBADMSG;
goto fail;
if (sz > 0) {
r = bus_message_parse_fields(m);
goto fail;
m->free_header = true;
m->free_fds = true;
*ret = m;
fail:
message_free(m);
sd_bus_message *m;
return NULL;
sd_bus_message **m,
const char *path,
const char *interface,
const char *member) {
sd_bus_message *t;
return -ENOMEM;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
goto fail;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
goto fail;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
goto fail;
fail:
sd_bus_message **m,
const char *destination,
const char *path,
const char *interface,
const char *member) {
sd_bus_message *t;
return -ENOMEM;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_PATH, SD_BUS_TYPE_OBJECT_PATH, path, &t->path);
goto fail;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_MEMBER, SD_BUS_TYPE_STRING, member, &t->member);
goto fail;
if (interface) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_INTERFACE, SD_BUS_TYPE_STRING, interface, &t->interface);
goto fail;
if (destination) {
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &t->destination);
goto fail;
fail:
message_free(t);
static int message_new_reply(
sd_bus_message **m) {
sd_bus_message *t;
return -ENOMEM;
goto fail;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, call->sender, &t->destination);
goto fail;
fail:
message_free(t);
sd_bus_message **m) {
sd_bus_message **m,
const sd_bus_error *e) {
sd_bus_message *t;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
goto fail;
if (e->message) {
goto fail;
fail:
message_free(t);
sd_bus_message **m,
const char *name,
const char *format,
sd_bus_message **m,
int error,
const sd_bus_error *p) {
if (sd_bus_error_is_set(p))
sd_bus_message **m,
int error,
const char *format,
const sd_bus_error *e,
sd_bus_message **m) {
sd_bus_message *t;
assert(m);
return -ENOMEM;
goto fail;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, bus->unique_name, &t->destination);
goto fail;
r = message_append_field_string(t, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, e->name, &t->error.name);
goto fail;
if (e->message) {
goto fail;
fail:
message_free(t);
m->n_ref++;
return NULL;
m->n_ref--;
if (m->n_ref > 0)
return NULL;
message_free(m);
return NULL;
return m->path;
return m->interface;
return m->member;
return m->destination;
return m->sender;
return &m->error;
if (m->monotonic <= 0)
return -ENODATA;
if (m->realtime <= 0)
return -ENODATA;
if (m->seqnum <= 0)
return -ENODATA;
return NULL;
return &m->creds;
const char *interface,
const char *member) {
const char *interface,
const char *member) {
assert(m);
if (m->n_containers == 0)
return &m->root_container;
assert(m);
if (m->poisoned)
return NULL;
if (m->n_body_parts <= 0) {
if (!part) {
m->poisoned = true;
return NULL;
m->n_body_parts ++;
return part;
static int part_make_space(
struct sd_bus_message *m,
assert(m);
if (m->poisoned)
return -ENOMEM;
m->poisoned = true;
if (n == MAP_FAILED) {
m->poisoned = true;
return -errno;
m->poisoned = true;
return -ENOMEM;
struct bus_container *c;
assert(m);
c = message_get_container(m);
if (!c->need_offsets)
return -ENOMEM;
struct bus_container *c;
assert(m);
if (expand <= 0)
if (c->array_size)
assert(m);
if (m->poisoned)
return NULL;
m->poisoned = true;
return NULL;
if (added > 0) {
bool add_new_part;
m->n_body_parts <= 0 ||
if (add_new_part) {
if (padding > 0) {
if (!part)
return NULL;
if (!part)
return NULL;
return NULL;
struct bus_container *c;
void *op;
return NULL;
if (padding > 0) {
if (add_offset) {
m->poisoned = true;
return NULL;
int *f, copy;
assert(m);
if (fd < 0)
return -EINVAL;
if (!m->allow_fds)
return -ENOTSUP;
if (copy < 0)
return -errno;
m->poisoned = true;
return -ENOMEM;
m->fds = f;
m->free_fds = true;
return copy;
struct bus_container *c;
c = message_get_container(m);
return -ENXIO;
if (c->enclosing != 0)
return -ENXIO;
m->poisoned = true;
return -ENOMEM;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
switch (type) {
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_STRING:
p = strempty(p);
case SD_BUS_TYPE_OBJECT_PATH:
return -EINVAL;
case SD_BUS_TYPE_BOOLEAN:
u8 = p && *(int*) p;
p = &u8;
case SD_BUS_TYPE_UNIX_FD:
return -EINVAL;
if (fd < 0)
return fd;
p = &u32;
return -ENOMEM;
if (stored)
switch (type) {
case SD_BUS_TYPE_STRING:
p = strempty(p);
case SD_BUS_TYPE_OBJECT_PATH:
return -EINVAL;
case SD_BUS_TYPE_SIGNATURE:
p = strempty(p);
case SD_BUS_TYPE_BOOLEAN:
u32 = p && *(int*) p;
p = &u32;
case SD_BUS_TYPE_UNIX_FD:
return -EINVAL;
if (fd < 0)
return fd;
p = &u32;
return -ENOMEM;
if (stored)
if (stored)
if (stored)
*stored = a;
m->n_fds ++;
c->index++;
sd_bus_message *m,
struct bus_container *c;
c = message_get_container(m);
return -ENXIO;
if (c->enclosing != 0)
return -ENXIO;
m->poisoned = true;
return -ENOMEM;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -ENOMEM;
return -ENOMEM;
(*s)[size] = 0;
c->index++;
sd_bus_message *m,
static int bus_message_open_array(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
bool *need_offsets) {
unsigned nindex;
int alignment, r;
assert(m);
assert(c);
return -EINVAL;
return -ENXIO;
return -ENXIO;
if (c->enclosing != 0)
return -ENXIO;
m->poisoned = true;
return -ENOMEM;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
if (alignment < 0)
return alignment;
return -ENOMEM;
*need_offsets = r == 0;
void *a, *op;
struct bus_body_part *o;
if (alignment < 0)
return alignment;
return -ENOMEM;
o = m->body_end;
return -ENOMEM;
if (o == m->body_end)
*(uint32_t*) a = 0;
*array_size = a;
static int bus_message_open_variant(
sd_bus_message *m,
struct bus_container *c,
const char *contents) {
assert(m);
assert(c);
return -EINVAL;
return -EINVAL;
return -ENXIO;
if (c->enclosing != 0)
return -ENXIO;
m->poisoned = true;
return -ENOMEM;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -ENOMEM;
size_t l;
return -ENOMEM;
*(uint8_t*) a = l;
c->index++;
static int bus_message_open_struct(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
bool *need_offsets) {
assert(m);
assert(c);
return -EINVAL;
size_t l;
return -ENXIO;
if (c->enclosing != 0)
return -ENXIO;
e = strextend(&c->signature, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_BEGIN), contents, CHAR_TO_STR(SD_BUS_TYPE_STRUCT_END), NULL);
m->poisoned = true;
return -ENOMEM;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
int alignment;
if (alignment < 0)
return alignment;
return -ENOMEM;
*need_offsets = r == 0;
return -ENOMEM;
static int bus_message_open_dict_entry(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
bool *need_offsets) {
assert(m);
assert(c);
return -EINVAL;
return -ENXIO;
size_t l;
return -ENXIO;
return -ENXIO;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
int alignment;
if (alignment < 0)
return alignment;
return -ENOMEM;
*need_offsets = r == 0;
return -ENOMEM;
sd_bus_message *m,
char type,
const char *contents) {
struct bus_container *c, *w;
char *signature;
bool need_offsets = false;
m->poisoned = true;
return -ENOMEM;
c = message_get_container(m);
if (!signature) {
m->poisoned = true;
return -ENOMEM;
r = -EINVAL;
w->index = 0;
assert(p);
return *(uint8_t*) p;
assert(p);
assert(m);
assert(c);
if (!BUS_MESSAGE_IS_GVARIANT(m))
if (c->need_offsets) {
uint8_t *a;
return -ENOMEM;
for (i = 0; i < c->n_offsets; i++)
return -ENOMEM;
uint8_t *a;
size_t l;
assert(m);
assert(c);
if (!BUS_MESSAGE_IS_GVARIANT(m))
return -ENOMEM;
uint8_t *a;
assert(m);
assert(c);
if (!BUS_MESSAGE_IS_GVARIANT(m))
size_t n;
r = signature_element_length(p, &n);
memcpy(t, p, n);
r = bus_gvariant_is_fixed_size(t);
n_variable++;
if (n_variable <= 0) {
return -ENOMEM;
return -ENOMEM;
for (i = 0, j = 0; i < c->n_offsets; i++) {
size_t n;
r = signature_element_length(p, &n);
memcpy(t, p, n);
r = bus_gvariant_is_fixed_size(t);
struct bus_container *c;
c = message_get_container(m);
return -EINVAL;
m->n_containers--;
r = bus_message_close_array(m, c);
r = bus_message_close_variant(m, c);
r = bus_message_close_struct(m, c, true);
const char *types;
unsigned n_struct;
unsigned n_array;
} TypeStack;
static int type_stack_push(TypeStack *stack, unsigned max, unsigned *i, const char *types, unsigned n_struct, unsigned n_array) {
if (*i >= max)
return -EINVAL;
static int type_stack_pop(TypeStack *stack, unsigned max, unsigned *i, const char **types, unsigned *n_struct, unsigned *n_array) {
sd_bus_message *m,
const char *types,
unsigned stack_ptr = 0;
assert(m);
if (!types)
r = sd_bus_message_close_container(m);
t = types;
n_array --;
types ++;
n_struct--;
case SD_BUS_TYPE_BYTE: {
uint8_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_UNIX_FD: {
uint32_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16: {
uint16_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE: {
uint64_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE: {
r = sd_bus_message_append_basic(m, *t, x);
case SD_BUS_TYPE_ARRAY: {
size_t k;
types += k;
n_struct -= k;
n_struct = k;
case SD_BUS_TYPE_VARIANT: {
return -EINVAL;
types = s;
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
size_t k;
r = signature_element_length(t, &k);
r = sd_bus_message_open_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
r = -EINVAL;
sd_bus_message *m,
char type,
void **ptr) {
return -EINVAL;
return -ENOMEM;
r = sd_bus_message_close_container(m);
*ptr = a;
char type,
const void *ptr,
if (size > 0)
sd_bus_message *m,
char type,
char type,
int memfd) {
return -EINVAL;
if (memfd < 0)
return -EINVAL;
if (m->sealed)
return -EPERM;
return -EINVAL;
if (m->poisoned)
return -ESTALE;
if (copy_fd < 0)
return copy_fd;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
if (!part)
return -ENOMEM;
return sd_bus_message_close_container(m);
struct bus_container *c;
if (copy_fd < 0)
return copy_fd;
if (size == 0)
return -EINVAL;
return -EINVAL;
c = message_get_container(m);
return -ENXIO;
if (c->enclosing != 0)
return -ENXIO;
m->poisoned = true;
return -ENOMEM;
if (!BUS_MESSAGE_IS_GVARIANT(m)) {
return -ENOMEM;
if (!part)
return -ENOMEM;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
m->poisoned = true;
return -ENOMEM;
c->index++;
STRV_FOREACH(i, l) {
return sd_bus_message_close_container(m);
uint8_t *a;
assert(m);
if (!BUS_MESSAGE_IS_GVARIANT(m))
return -ENOMEM;
for (i = 0; i < m->n_header_offsets; i++)
size_t l, a;
assert(m);
if (m->sealed)
return -EPERM;
if (m->n_containers > 0)
return -EBADMSG;
if (m->poisoned)
return -ESTALE;
m->enforced_reply_signature &&
return -ENOMSG;
r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL);
if (m->n_fds > 0) {
r = bus_message_close_header(m);
l = BUS_MESSAGE_FIELDS_SIZE(m);
a = ALIGN8(l) - l;
m->sealed = true;
return -EINVAL;
if (p == MAP_FAILED)
return -errno;
static int buffer_peek(const void *p, uint32_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) {
return -EBADMSG;
if (((const uint8_t*) p)[k] != 0)
return -EBADMSG;
struct bus_container *c;
assert(m);
c = message_get_container(m);
struct bus_container *c;
assert(m);
c = message_get_container(m);
if (BUS_MESSAGE_IS_GVARIANT(m))
if (message_end_of_signature(m))
assert(m);
begin = 0;
while (part) {
return NULL;
return NULL;
return part;
return NULL;
assert(m);
assert(c);
if (!BUS_MESSAGE_IS_GVARIANT(m))
int sz;
if (sz < 0) {
int alignment;
goto end;
goto end;
c->offset_index++;
} else if (c->enclosing == 0 ||
int alignment;
size_t n, j;
goto end;
c->offset_index++;
goto end;
end:
c->item_size = 0;
static int message_peek_body(
sd_bus_message *m,
void **ret) {
uint8_t *q;
assert(m);
return -EBADMSG;
if (!part)
return -EBADMSG;
for (k = 0; k < padding; k++)
return -EBADMSG;
return -EBADMSG;
if (ret)
*ret = q;
if (memchr(s, 0, l))
if (!validate_nul(s, l))
if (!utf8_is_valid(s))
if (!validate_nul(s, l))
if (!signature_is_valid(s, true))
if (!validate_nul(s, l))
if (!object_path_is_valid(s))
struct bus_container *c;
if (message_end_of_signature(m))
return -ENXIO;
c = message_get_container(m);
return -ENXIO;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
bool ok;
if (!ok)
return -EBADMSG;
return -EBADMSG;
switch (type) {
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
*(int*) p = !!*(uint8_t*) q;
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_UNIX_FD: {
uint32_t j;
if (j >= m->n_fds)
return -EBADMSG;
*(int*) p = m->fds[j];
uint32_t l;
bool ok;
if (!ok)
return -EBADMSG;
uint8_t l;
l = *(uint8_t*) q;
if (!validate_signature(q, l))
return -EBADMSG;
switch (type) {
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
*(int*) p = !!*(uint32_t*) q;
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_UNIX_FD: {
uint32_t j;
if (j >= m->n_fds)
return -EBADMSG;
*(int*) p = m->fds[j];
c->index++;
static int bus_message_enter_array(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
int r, alignment;
assert(m);
assert(c);
return -EINVAL;
return -ENXIO;
return -ENXIO;
return -ENXIO;
if (!BUS_MESSAGE_IS_GVARIANT(m)) {
return -EBADMSG;
if (alignment < 0)
return alignment;
} else if (c->item_size <= 0) {
*item_size = 0;
*n_offsets = 0;
*n_offsets = 0;
return -EBADMSG;
return -EBADMSG;
if (!*offsets)
return -ENOMEM;
for (i = 0; i < *n_offsets; i++) {
size_t x;
return -EBADMSG;
return -EBADMSG;
static int bus_message_enter_variant(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
uint8_t l;
assert(m);
assert(c);
return -EINVAL;
return -EINVAL;
return -ENXIO;
return -ENXIO;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -EBADMSG;
return -EBADMSG;
return -ENXIO;
l = *(uint8_t*) q;
if (!validate_signature(q, l))
return -EBADMSG;
return -ENXIO;
c->index++;
static int build_struct_offsets(
sd_bus_message *m,
const char *signature,
assert(m);
*item_size = 0;
*n_offsets = 0;
if (sz <= 0)
return -EBADMSG;
p = signature;
size_t n;
r = signature_element_length(p, &n);
memcpy(t, p, n);
r = bus_gvariant_is_fixed_size(t);
n_variable ++;
n_total++;
return -EBADMSG;
v = n_variable;
if (!*offsets)
return -ENOMEM;
*n_offsets = 0;
p = signature;
r = signature_element_length(p, &n);
memcpy(t, p, n);
k = bus_gvariant_get_size(t);
size_t x;
if (x >= size)
return -EBADMSG;
return -EBADMSG;
assert(v == 0);
static int enter_struct_or_dict_entry(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
assert(m);
assert(c);
if (!BUS_MESSAGE_IS_GVARIANT(m)) {
} else if (c->item_size <= 0) {
*item_size = 0;
*n_offsets = 0;
static int bus_message_enter_struct(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
size_t l;
assert(m);
assert(c);
return -EINVAL;
return -ENXIO;
return -ENXIO;
static int bus_message_enter_dict_entry(
sd_bus_message *m,
struct bus_container *c,
const char *contents,
size_t l;
assert(m);
assert(c);
return -EINVAL;
return -ENXIO;
return -ENXIO;
char type,
const char *contents) {
struct bus_container *c, *w;
char *signature;
const char *cc;
char tt;
return -ENXIO;
return -ENXIO;
return -EBADMSG;
return -ENOMEM;
if (message_end_of_signature(m))
return -ENXIO;
c = message_get_container(m);
if (!signature)
return -ENOMEM;
r = -EINVAL;
w->index = 0;
w->offset_index = 0;
struct bus_container *c;
unsigned saved;
c = message_get_container(m);
return -EBUSY;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -EBUSY;
uint32_t l;
return -EBUSY;
m->n_containers--;
c = message_get_container(m);
struct bus_container *c;
assert(m);
c = message_get_container(m);
m->n_containers--;
c = message_get_container(m);
struct bus_container *c;
if (message_end_of_signature(m))
goto eof;
goto eof;
c = message_get_container(m);
if (contents)
if (type)
if (contents) {
size_t l;
char *sig;
if (!sig)
return -ENOMEM;
if (type)
if (contents) {
size_t l;
char *sig;
if (!sig)
return -ENOMEM;
if (type)
*type = c->signature[c->index] == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY;
if (contents) {
if (BUS_MESSAGE_IS_GVARIANT(m)) {
size_t k;
return -EBADMSG;
if (k > c->item_size)
return -EBADMSG;
if (!c->peeked_signature)
return -ENOMEM;
return -EBADMSG;
l = *(uint8_t*) q;
if (!validate_signature(q, l))
return -EBADMSG;
*contents = q;
if (type)
return -EINVAL;
eof:
if (type)
*type = 0;
if (contents)
struct bus_container *c;
if (complete) {
m->rindex = 0;
c = message_get_container(m);
c = message_get_container(m);
c->offset_index = 0;
c->index = 0;
c->offset_index = 0;
static int message_read_ap(
sd_bus_message *m,
const char *types,
unsigned stack_ptr = 0;
unsigned n_loop = 0;
assert(m);
n_loop++;
r = sd_bus_message_exit_container(m);
t = types;
n_array --;
types ++;
n_struct--;
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_UNIX_FD: {
r = sd_bus_message_read_basic(m, *t, p);
return -ENXIO;
case SD_BUS_TYPE_ARRAY: {
size_t k;
return -ENXIO;
types += k;
n_struct -= k;
n_struct = k;
case SD_BUS_TYPE_VARIANT: {
return -EINVAL;
return -ENXIO;
types = s;
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
size_t k;
r = signature_element_length(t, &k);
r = sd_bus_message_enter_container(m, *t == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
return -ENXIO;
return -EINVAL;
switch (*types) {
case SD_BUS_TYPE_BYTE:
case SD_BUS_TYPE_BOOLEAN:
case SD_BUS_TYPE_INT16:
case SD_BUS_TYPE_UINT16:
case SD_BUS_TYPE_INT32:
case SD_BUS_TYPE_UINT32:
case SD_BUS_TYPE_INT64:
case SD_BUS_TYPE_UINT64:
case SD_BUS_TYPE_DOUBLE:
case SD_BUS_TYPE_STRING:
case SD_BUS_TYPE_OBJECT_PATH:
case SD_BUS_TYPE_SIGNATURE:
case SD_BUS_TYPE_UNIX_FD:
case SD_BUS_TYPE_ARRAY: {
size_t k;
r = sd_bus_message_skip(m, s);
r = sd_bus_message_exit_container(m);
case SD_BUS_TYPE_VARIANT: {
const char *contents;
if (x != SD_BUS_TYPE_VARIANT)
return -ENXIO;
assert(r != 0);
r = sd_bus_message_exit_container(m);
case SD_BUS_TYPE_STRUCT_BEGIN:
case SD_BUS_TYPE_DICT_ENTRY_BEGIN: {
size_t k;
r = sd_bus_message_enter_container(m, *types == SD_BUS_TYPE_STRUCT_BEGIN ? SD_BUS_TYPE_STRUCT : SD_BUS_TYPE_DICT_ENTRY, s);
r = sd_bus_message_skip(m, s);
assert(r != 0);
r = sd_bus_message_exit_container(m);
return -EINVAL;
char type,
const void **ptr,
struct bus_container *c;
c = message_get_container(m);
if (BUS_MESSAGE_IS_GVARIANT(m)) {
if (align < 0)
return align;
if (align < 0)
return align;
if (sz == 0)
goto fail;
r = sd_bus_message_exit_container(m);
goto fail;
*ptr = (const void*) p;
fail:
static int message_peek_fields(
sd_bus_message *m,
void **ret) {
assert(m);
static int message_peek_field_uint32(
sd_bus_message *m,
assert(m);
return -EBADMSG;
if (ret)
static int message_peek_field_string(
sd_bus_message *m,
bool (*validate)(const char *p),
const char **ret) {
uint32_t l;
assert(m);
if (BUS_MESSAGE_IS_GVARIANT(m)) {
if (item_size <= 0)
return -EBADMSG;
if (validate) {
if (!validate_nul(q, l))
return -EBADMSG;
if (!validate(q))
return -EBADMSG;
if (!validate_string(q, l))
return -EBADMSG;
if (ret)
*ret = q;
static int message_peek_field_signature(
sd_bus_message *m,
const char **ret) {
size_t l;
assert(m);
if (BUS_MESSAGE_IS_GVARIANT(m)) {
if (item_size <= 0)
return -EBADMSG;
l = *(uint8_t*) q;
if (!validate_signature(q, l))
return -EBADMSG;
if (ret)
*ret = q;
static int message_skip_fields(
sd_bus_message *m,
const char **signature) {
assert(m);
size_t l;
t = **signature;
if (t == SD_BUS_TYPE_STRING) {
(*signature)++;
} else if (t == SD_BUS_TYPE_OBJECT_PATH) {
(*signature)++;
} else if (t == SD_BUS_TYPE_SIGNATURE) {
(*signature)++;
} else if (bus_type_is_basic(t)) {
k = bus_type_get_size(t);
(*signature)++;
} else if (t == SD_BUS_TYPE_ARRAY) {
int alignment;
s = sig;
if (alignment < 0)
return alignment;
return -EBADMSG;
} else if (t == SD_BUS_TYPE_VARIANT) {
(*signature)++;
} else if (t == SD_BUS_TYPE_STRUCT ||
t == SD_BUS_TYPE_DICT_ENTRY) {
s = sig;
*signature += l;
return -EINVAL;
bool unix_fds_set = false;
unsigned n_offsets = 0;
assert(m);
if (BUS_MESSAGE_IS_GVARIANT(m)) {
if (sz > 0) {
return -EBADMSG;
return -EBADMSG;
ri = 0;
const char *signature;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
if (i >= n_offsets)
ri = 0;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -EBADMSG;
return -EBADMSG;
if (!sig)
return -ENOMEM;
item_size = b - (char*) q;
switch (*header) {
return -EBADMSG;
case BUS_MESSAGE_HEADER_PATH:
if (m->path)
return -EBADMSG;
return -EBADMSG;
if (m->interface)
return -EBADMSG;
return -EBADMSG;
if (m->member)
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
if (m->destination)
return -EBADMSG;
return -EBADMSG;
if (m->sender)
return -EBADMSG;
return -EBADMSG;
case BUS_MESSAGE_HEADER_SIGNATURE: {
return -EBADMSG;
return -EBADMSG;
c = strdup(s);
return -ENOMEM;
case BUS_MESSAGE_HEADER_REPLY_SERIAL: {
if (m->reply_cookie != 0)
return -EBADMSG;
return -EBADMSG;
if (m->reply_cookie == 0)
return -EBADMSG;
if (unix_fds_set)
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
unix_fds_set = true;
if (!BUS_MESSAGE_IS_GVARIANT(m))
return -EBADMSG;
case SD_BUS_MESSAGE_SIGNAL:
return -EBADMSG;
return -EBADMSG;
if (m->reply_cookie == 0)
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
r = build_struct_offsets(
return message_append_field_string(m, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, destination, &m->destination);
assert(m);
return -ENOMEM;
*buffer = p;
assert(m);
assert(l);
r = strv_extend(l, s);
r = sd_bus_message_exit_container(m);
*l = strv;
const char *t = NULL;
assert(m);
r = sd_bus_message_rewind(m, true);
return NULL;
char type;
return NULL;
return NULL;
return NULL;
assert(h);
assert(h);
return -EBADMSG;
struct bus_container *c;
bool done_something = false;
const char *contents;
char type;
double d64;
const char *string;
} basic;
done_something = true;
r = sd_bus_message_close_container(m);
assert(r > 0);
} while (all);
return done_something;
r = sd_bus_message_peek_type(m, &t, &c);
return m->bus;
assert(m);
assert(*m);
case SD_BUS_MESSAGE_SIGNAL:
r = sd_bus_message_new_method_call(bus, &n, (*m)->destination, (*m)->path, (*m)->interface, (*m)->member);
return -ENOMEM;
r = message_append_field_string(n, BUS_MESSAGE_HEADER_ERROR_NAME, SD_BUS_TYPE_STRING, (*m)->error.name, &n->error.message);
return -EINVAL;
r = message_append_field_string(n, BUS_MESSAGE_HEADER_DESTINATION, SD_BUS_TYPE_STRING, (*m)->destination, &n->destination);
r = message_append_field_string(n, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, (*m)->sender, &n->sender);
n->header->flags |= (*m)->header->flags & (BUS_MESSAGE_NO_REPLY_EXPECTED|BUS_MESSAGE_NO_AUTO_START);
r = sd_bus_message_copy(n, *m, true);
sd_bus_message_unref(*m);
n = NULL;
assert(m);
return message_append_field_string(m, BUS_MESSAGE_HEADER_SENDER, SD_BUS_TYPE_STRING, sender, &m->sender);