bus-message.c revision b267a6d20464a138cae916a676f2c382c51d52de
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering This file is part of systemd.
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering Copyright 2013 Lennart Poettering
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering systemd is free software; you can redistribute it and/or modify it
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering under the terms of the GNU Lesser General Public License as published by
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering (at your option) any later version.
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering systemd is distributed in the hope that it will be useful, but
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering Lesser General Public License for more details.
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering You should have received a copy of the GNU Lesser General Public License
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poetteringstatic int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored);
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poetteringstatic void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) {
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering return (void*) p;
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering return (void*) p;
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering if ((uint8_t*) p >= (uint8_t*) old_base + sz)
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering return (void*) p;
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering return (uint8_t*) new_base + ((uint8_t*) p - (uint8_t*) old_base);
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poetteringstatic void message_free_part(sd_bus_message *m, struct bus_body_part *part) {
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering /* If we can reuse the memfd, try that. For that it
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering * can't be sealed yet. */
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering bus_kernel_push_memfd(m->bus, part->memfd, part->data, part->mapped, part->allocated);
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering assert_se(munmap(part->mmap_begin, part->mapped) == 0);
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poetteringstatic void message_reset_parts(sd_bus_message *m) {
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering while (m->n_body_parts > 0) {
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poetteringstatic void message_reset_containers(sd_bus_message *m) {
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering for (i = 0; i < m->n_containers; i++) {
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering m->n_containers = m->containers_allocated = 0;
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poetteringstatic void message_free(sd_bus_message *m) {
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering bus_kernel_cmd_free(m->bus, (uint8_t *) m->kdbus - (uint8_t *) m->bus->kdbus_buffer);
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poettering free(m->root_container.peeked_signature);
34829a324b1ffc6cb8405223329a9c55cd8de0eeLennart Poetteringstatic void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) {
assert(m);
if (m->poisoned)
return NULL;
goto poison;
if (m->free_header) {
if (!np)
goto poison;
if (!np)
goto poison;
m->free_header = true;
if (add_offset) {
goto poison;
m->poisoned = true;
return NULL;
static int message_append_field_string(
sd_bus_message *m,
uint64_t h,
char type,
const char **ret) {
size_t l;
uint8_t *p;
assert(m);
return -EINVAL;
l = strlen(s);
return -EINVAL;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -ENOMEM;
*((uint64_t*) p) = h;
if (ret)
return -ENOMEM;
p[0] = (uint8_t) h;
if (ret)
static int message_append_field_signature(
sd_bus_message *m,
uint64_t h,
const char **ret) {
size_t l;
uint8_t *p;
assert(m);
return -EINVAL;
l = strlen(s);
return -EINVAL;
if (BUS_MESSAGE_IS_GVARIANT(m))
return -ENOMEM;
p[0] = (uint8_t) h;
if (ret)
uint8_t *p;
assert(m);
return -EINVAL;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -ENOMEM;
*((uint64_t*) p) = h;
return -ENOMEM;
p[0] = (uint8_t) h;
uint8_t *p;
assert(m);
return -EINVAL;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -ENOMEM;
*((uint64_t*) p) = h;
return -ENOMEM;
p[0] = (uint8_t) h;
assert(m);
if (BUS_MESSAGE_IS_GVARIANT(m))
return -ENOTSUP;
void *header,
void *footer,
int *fds,
unsigned n_fds,
const char *label,
sd_bus_message *m;
struct bus_header *h;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
h = header;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
if (label) {
m = malloc0(a);
return -ENOMEM;
m->sealed = true;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
return -EBADMSG;
if (ucred) {
if (label) {
*ret = m;
void *buffer,
int *fds,
unsigned n_fds,
const char *label,
sd_bus_message *m;
bus,
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;
if (t->reply_cookie == 0)
return -ENOTSUP;
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,
assert(m);
assert(m);
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;
uint64_t c;
c = BUS_MESSAGE_COOKIE(m);
return -ENODATA;
if (m->reply_cookie == 0)
return -ENODATA;
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;
sd_bus_message *m,
const char *interface,
const char *member) {
sd_bus_message *m,
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)
static void *message_extend_body(
sd_bus_message *m,
bool add_offset,
bool force_inline) {
assert(m);
if (m->poisoned)
return NULL;
m->poisoned = true;
return NULL;
if (added > 0) {
bool add_new_part;
m->n_body_parts <= 0 ||
(force_inline && m->body_end->size > MEMFD_MIN_SIZE); /* if this must be an inlined extension, let's create a new part if the previous part is large enough to be inlined */
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(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: {
uint64_t x;
r = sd_bus_message_append_basic(m, *t, &x);
case SD_BUS_TYPE_DOUBLE: {
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;
sd_bus_message *m,
char type,
const void *ptr,
if (size > 0)
sd_bus_message *m,
char type,
sd_bus_message *m,
char type,
int memfd,
if (copy_fd < 0)
return copy_fd;
return -EMSGSIZE;
return -EINVAL;
return -EINVAL;
return -EINVAL;
return -ENOMEM;
if (!part)
return -ENOMEM;
return sd_bus_message_close_container(m);
sd_bus_message *m,
int memfd,
struct bus_container *c;
if (copy_fd < 0)
return copy_fd;
return -EMSGSIZE;
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);
assert(m);
if (BUS_MESSAGE_IS_GVARIANT(m)) {
const char *signature;
uint8_t *a;
return -ENOMEM;
for (i = 0; i < m->n_header_offsets; i++)
sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l, 1);
return -ENOMEM;
*(uint8_t*) d = 0;
m->footer = d;
size_t a;
assert(m);
if (m->sealed)
return -EPERM;
if (m->n_containers > 0)
return -EBADMSG;
if (m->poisoned)
return -ESTALE;
return -ENOTSUP;
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);
if (BUS_MESSAGE_IS_GVARIANT(m))
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;
if (!types) {
struct bus_container *c;
size_t l;
if (message_end_of_signature(m))
return -ENXIO;
c = message_get_container(m);
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;
sd_bus_message *m,
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_uint64(
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)) {
return -EBADMSG;
if (p < (char*) m->footer)
return -EBADMSG;
return -ENOMEM;
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 (field_type) {
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;
return -EBADMSG;
c = strdup(s);
return -ENOMEM;
if (m->reply_cookie != 0)
return -EBADMSG;
if (BUS_MESSAGE_IS_GVARIANT(m)) {
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;
if (m->reply_cookie != 0)
return -EBADMSG;
return -EBADMSG;
if (m->reply_cookie != 0)
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(
m->user_body_size,
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 *contents;
char type;
assert(m);
r = sd_bus_message_rewind(m, true);
return -ENXIO;
return -ENXIO;
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);