diff --git a/TODO b/TODO index 88d0885bec5..89034c5309a 100644 --- a/TODO +++ b/TODO @@ -1356,7 +1356,6 @@ Features: - longer term: priority inheritance - dbus spec updates: - NameLost/NameAcquired obsolete - - GVariant - path escaping - update systemd.special(7) to mention that dbus.socket is only about the compatibility socket now diff --git a/docs/GVARIANT-SERIALIZATION.md b/docs/GVARIANT-SERIALIZATION.md deleted file mode 100644 index 3dca54ebe3d..00000000000 --- a/docs/GVARIANT-SERIALIZATION.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: GVariant D-Bus Message Serialization -category: Interfaces -layout: default -SPDX-License-Identifier: LGPL-2.1-or-later ---- - -# GVariant D-Bus Message Serialization - -We stay as close to the original dbus1 framing as possible, but make -certain changes to adapt for GVariant. dbus1 has the following -framing: - - 1. A fixed header of "yyyyuu" - 2. Additional header fields of "a(yv)" - 3. Padding with NUL bytes to pad up to next 8byte boundary - 4. The body - -Note that the body is not padded at the end, the complete message -hence might have a non-aligned size. Reading multiple messages at once -will hence result in possibly unaligned messages in memory. - -The header consists of the following: - - y Endianness, 'l' or 'B' - y Message Type - y Flags - y Protocol version, '1' - u Length of the body, i.e. the length of part 4 above - u 32bit Serial number - - = 12 bytes - -This header is then followed by the fields array, whose first value is -a 32bit array size. - -When using GVariant we keep the basic structure in place, only -slightly alter the header, and define protocol version '2'. The new -header: - - y Endianness, 'l' or 'B' - y Message Type - y Flags - y Protocol version, '2' - u Reserved, must be 0 - t 64bit Cookie - - = 16 bytes - -This is then followed by the GVariant fields array ("a{tv}"), and -finally the actual body as variant (v). Putting this altogether a -packet on dbus2 hence qualifies as a fully compliant GVariant -structure of (yyyyuta{tv}v). - -For details on gvariant, see: - -https://people.gnome.org/~desrt/gvariant-serialisation.pdf - -Regarding the framing of dbus2, also see: - -https://wiki.gnome.org/Projects/GLib/GDBus/Version2 - -The first four bytes of the header are defined the same way for dbus1 -and dbus2. The first bytes contain the endianness field and the -protocol version, so that the remainder of the message can be safely -made sense of just by looking at the first 32bit. - -Note that the length of the body is no longer included in the header -on dbus2! In fact, the message size must be known in advance, from the -underlying transport in order to parse dbus2 messages, while it is -directly included in dbus1 message headers. This change of semantics -is an effect of GVariant's basic design. - -The serial number has been renamed cookie and has been extended from -32bit to 64bit. It is recommended to avoid the higher 32bit of the -cookie field though, to simplify compatibility with dbus1 peers. Note -that not only the cookie/serial field in the fixed header, but also -the reply_cookie/reply_serial additional header field has been -increased from 32bit to 64bit, too! - -The header field identifiers have been extended from 8bit to -64bit. This has been done to simplify things, and has no effect -on the serialization size, as due to alignment for each 8bit -header field identifier 56 bits of padding had to be added. - -Note that the header size changed, due to these changes. However, -consider that on dbus1 the beginning of the fields array contains the -32bit array size (since that is how arrays are encoded on dbus1), -thus, if one considers that size part of the header, instead of the -array, the size of the header on dbus1 and dbus2 stays identical, at -16 bytes. - - 0 4 8 12 16 - Common: | E | T | F | V | ... - - dbus1: | (as above) | Body Length | Serial | Fields Length | Fields array ... - - gvariant: | (as above) | Reserved | Cookie | Fields array ... - -And that's already it. - -Note: To simplify parsing, valid dbus2 messages must include the entire - fixed header and additional header fields in a single non-memfd - message part. Also, the signature string of the body variant all the - way to the end of the message must be in a single non-memfd part - too. The parts for this extended header and footer can be the same - one, and can also continue any amount of additional body bytes. - -Note: The GVariant "MAYBE" type is not supported, so that messages can - be fully converted forth and back between dbus1 and gvariant - representations. diff --git a/meson.build b/meson.build index c5540fc6fe2..731456ba075 100644 --- a/meson.build +++ b/meson.build @@ -3928,7 +3928,6 @@ install_data('LICENSE.GPL2', 'docs/TRANSIENT-SETTINGS.md', 'docs/TRANSLATORS.md', 'docs/UIDS-GIDS.md', - 'docs/GVARIANT-SERIALIZATION.md', install_dir : docdir) install_subdir('LICENSES', diff --git a/src/basic/macro.h b/src/basic/macro.h index 97272791551..e3ee7bfee9e 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -110,25 +110,6 @@ #error "neither int nor long are four bytes long?!?" #endif -/* Rounds up */ - -#define ALIGN4(l) (((l) + 3) & ~3) -#define ALIGN8(l) (((l) + 7) & ~7) - -#if __SIZEOF_POINTER__ == 8 -#define ALIGN(l) ALIGN8(l) -#elif __SIZEOF_POINTER__ == 4 -#define ALIGN(l) ALIGN4(l) -#else -#error "Wut? Pointers are neither 4 nor 8 bytes long?" -#endif - -#define ALIGN_PTR(p) ((void*) ALIGN((unsigned long) (p))) -#define ALIGN4_PTR(p) ((void*) ALIGN4((unsigned long) (p))) -#define ALIGN8_PTR(p) ((void*) ALIGN8((unsigned long) (p))) - -#define ALIGN_TO_PTR(p, ali) ((void*) ALIGN_TO((unsigned long) (p), (ali))) - /* align to next higher power-of-2 (except for: 0 => 0, overflow => 0) */ static inline unsigned long ALIGN_POWER2(unsigned long u) { diff --git a/src/basic/static-destruct.h b/src/basic/static-destruct.h index a41c0e30d53..97baac7abb0 100644 --- a/src/basic/static-destruct.h +++ b/src/basic/static-destruct.h @@ -55,9 +55,9 @@ static inline void static_destruct(void) { if (!__start_SYSTEMD_STATIC_DESTRUCT) return; - d = ALIGN_TO_PTR(__start_SYSTEMD_STATIC_DESTRUCT, sizeof(void*)); + d = ALIGN_PTR(__start_SYSTEMD_STATIC_DESTRUCT); while (d < __stop_SYSTEMD_STATIC_DESTRUCT) { d->destroy(d->data); - d = ALIGN_TO_PTR(d + 1, sizeof(void*)); + d = ALIGN_PTR(d + 1); } } diff --git a/src/boot/efi/cpio.c b/src/boot/efi/cpio.c index 66ef5da3138..aebffb51b7c 100644 --- a/src/boot/efi/cpio.c +++ b/src/boot/efi/cpio.c @@ -96,12 +96,12 @@ static EFI_STATUS pack_cpio_one( return EFI_OUT_OF_RESOURCES; /* Align the whole header to 4 byte size */ - l = ALIGN_TO(l, 4); + l = ALIGN4(l); if (l == UINTN_MAX) /* overflow check */ return EFI_OUT_OF_RESOURCES; /* Align the contents to 4 byte size */ - q = ALIGN_TO(contents_size, 4); + q = ALIGN4(contents_size); if (q == UINTN_MAX) /* overflow check */ return EFI_OUT_OF_RESOURCES; @@ -188,7 +188,7 @@ static EFI_STATUS pack_cpio_dir( l += path_size; /* Align the whole header to 4 byte size */ - l = ALIGN_TO(l, 4); + l = ALIGN4(l); if (l == UINTN_MAX) /* overflow check */ return EFI_OUT_OF_RESOURCES; diff --git a/src/boot/efi/stub.c b/src/boot/efi/stub.c index 36becafa083..f335d3782d5 100644 --- a/src/boot/efi/stub.c +++ b/src/boot/efi/stub.c @@ -34,7 +34,7 @@ static EFI_STATUS combine_initrd( /* Combines four initrds into one, by simple concatenation in memory */ - n = ALIGN_TO(initrd_size, 4); /* main initrd might not be padded yet */ + n = ALIGN4(initrd_size); /* main initrd might not be padded yet */ if (credential_initrd) { if (n > UINTN_MAX - credential_initrd_size) return EFI_OUT_OF_RESOURCES; @@ -71,7 +71,7 @@ static EFI_STATUS combine_initrd( memcpy(p, PHYSICAL_ADDRESS_TO_POINTER(initrd_base), initrd_size); p += initrd_size; - pad = ALIGN_TO(initrd_size, 4) - initrd_size; + pad = ALIGN4(initrd_size) - initrd_size; if (pad > 0) { memset(p, 0, pad); p += pad; diff --git a/src/fundamental/macro-fundamental.h b/src/fundamental/macro-fundamental.h index bb9e779dd23..f78c62ef250 100644 --- a/src/fundamental/macro-fundamental.h +++ b/src/fundamental/macro-fundamental.h @@ -320,6 +320,14 @@ static inline size_t ALIGN_TO(size_t l, size_t ali) { return ((l + ali - 1) & ~(ali - 1)); } +#define ALIGN4(l) ALIGN_TO(l, 4) +#define ALIGN8(l) ALIGN_TO(l, 8) +#ifndef SD_BOOT +/* libefi also provides ALIGN, and we do not use them in sd-boot explicitly. */ +#define ALIGN(l) ALIGN_TO(l, sizeof(void*)) +#define ALIGN_PTR(p) ((void*) ALIGN((uintptr_t) (p))) +#endif + /* Same as ALIGN_TO but callable in constant contexts. */ #define CONST_ALIGN_TO(l, ali) \ __builtin_choose_expr( \ diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index c3eef87b840..443e0395415 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -95,8 +95,6 @@ libsystemd_sources = files( 'sd-bus/bus-dump.h', 'sd-bus/bus-error.c', 'sd-bus/bus-error.h', - 'sd-bus/bus-gvariant.c', - 'sd-bus/bus-gvariant.h', 'sd-bus/bus-internal.c', 'sd-bus/bus-internal.h', 'sd-bus/bus-introspect.c', @@ -262,12 +260,6 @@ tests += [ [files('sd-bus/test-bus-vtable.c', 'sd-bus/test-vtable-data.h')], - [files('sd-bus/test-bus-gvariant.c'), - [], - [libglib, - libgobject, - libgio]], - [files('sd-bus/test-bus-creds.c')], [files('sd-bus/test-bus-match.c')], diff --git a/src/libsystemd/sd-bus/bus-dump.c b/src/libsystemd/sd-bus/bus-dump.c index 050eec3a7cd..d67a170a2d9 100644 --- a/src/libsystemd/sd-bus/bus-dump.c +++ b/src/libsystemd/sd-bus/bus-dump.c @@ -79,7 +79,7 @@ _public_ int sd_bus_message_dump(sd_bus_message *m, FILE *f, uint64_t flags) { /* Display synthetic message serial number in a more readable * format than UINT32_MAX */ - if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL) + if (BUS_MESSAGE_COOKIE(m) == UINT32_MAX) fprintf(f, " Cookie=-1"); else fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m)); diff --git a/src/libsystemd/sd-bus/bus-error.c b/src/libsystemd/sd-bus/bus-error.c index bdfa145ab7d..2454a95b9db 100644 --- a/src/libsystemd/sd-bus/bus-error.c +++ b/src/libsystemd/sd-bus/bus-error.c @@ -92,7 +92,7 @@ static int bus_error_name_to_errno(const char *name) { } } - m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*)); + m = ALIGN_PTR(__start_SYSTEMD_BUS_ERROR_MAP); while (m < __stop_SYSTEMD_BUS_ERROR_MAP) { /* For magic ELF error maps, the end marker might * appear in the middle of things, since multiple maps @@ -101,7 +101,7 @@ static int bus_error_name_to_errno(const char *name) { * boundary, which is the selected alignment for the * arrays. */ if (m->code == BUS_ERROR_MAP_END_MARKER) { - m = ALIGN_TO_PTR(m + 1, sizeof(void*)); + m = ALIGN_PTR(m + 1); continue; } diff --git a/src/libsystemd/sd-bus/bus-gvariant.c b/src/libsystemd/sd-bus/bus-gvariant.c deleted file mode 100644 index 07decfd1f3d..00000000000 --- a/src/libsystemd/sd-bus/bus-gvariant.c +++ /dev/null @@ -1,299 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include -#include - -#include "sd-bus.h" - -#include "bus-gvariant.h" -#include "bus-signature.h" -#include "bus-type.h" - -int bus_gvariant_get_size(const char *signature) { - const char *p; - int sum = 0, r; - - /* For fixed size structs. Fails for variable size structs. */ - - p = signature; - while (*p != 0) { - size_t n; - - r = signature_element_length(p, &n); - if (r < 0) - return r; - else { - char t[n+1]; - - memcpy(t, p, n); - t[n] = 0; - - r = bus_gvariant_get_alignment(t); - if (r < 0) - return r; - - sum = ALIGN_TO(sum, r); - } - - switch (*p) { - - case SD_BUS_TYPE_BOOLEAN: - case SD_BUS_TYPE_BYTE: - sum += 1; - break; - - case SD_BUS_TYPE_INT16: - case SD_BUS_TYPE_UINT16: - sum += 2; - break; - - case SD_BUS_TYPE_INT32: - case SD_BUS_TYPE_UINT32: - case SD_BUS_TYPE_UNIX_FD: - sum += 4; - break; - - case SD_BUS_TYPE_INT64: - case SD_BUS_TYPE_UINT64: - case SD_BUS_TYPE_DOUBLE: - sum += 8; - break; - - case SD_BUS_TYPE_STRUCT_BEGIN: - case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { - if (n == 2) { - /* unary type () has fixed size of 1 */ - r = 1; - } else { - char t[n-1]; - - memcpy(t, p + 1, n - 2); - t[n - 2] = 0; - - r = bus_gvariant_get_size(t); - if (r < 0) - return r; - } - - sum += r; - break; - } - - case SD_BUS_TYPE_STRING: - case SD_BUS_TYPE_OBJECT_PATH: - case SD_BUS_TYPE_SIGNATURE: - case SD_BUS_TYPE_ARRAY: - case SD_BUS_TYPE_VARIANT: - return -EINVAL; - - default: - assert_not_reached(); - } - - p += n; - } - - r = bus_gvariant_get_alignment(signature); - if (r < 0) - return r; - - return ALIGN_TO(sum, r); -} - -int bus_gvariant_get_alignment(const char *signature) { - size_t alignment = 1; - const char *p; - int r; - - p = signature; - while (*p != 0 && alignment < 8) { - size_t n; - int a; - - r = signature_element_length(p, &n); - if (r < 0) - return r; - - switch (*p) { - - case SD_BUS_TYPE_BYTE: - case SD_BUS_TYPE_BOOLEAN: - case SD_BUS_TYPE_STRING: - case SD_BUS_TYPE_OBJECT_PATH: - case SD_BUS_TYPE_SIGNATURE: - a = 1; - break; - - case SD_BUS_TYPE_INT16: - case SD_BUS_TYPE_UINT16: - a = 2; - break; - - case SD_BUS_TYPE_INT32: - case SD_BUS_TYPE_UINT32: - case SD_BUS_TYPE_UNIX_FD: - a = 4; - break; - - case SD_BUS_TYPE_INT64: - case SD_BUS_TYPE_UINT64: - case SD_BUS_TYPE_DOUBLE: - case SD_BUS_TYPE_VARIANT: - a = 8; - break; - - case SD_BUS_TYPE_ARRAY: { - char t[n]; - - memcpy(t, p + 1, n - 1); - t[n - 1] = 0; - - a = bus_gvariant_get_alignment(t); - break; - } - - case SD_BUS_TYPE_STRUCT_BEGIN: - case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { - char t[n-1]; - - memcpy(t, p + 1, n - 2); - t[n - 2] = 0; - - a = bus_gvariant_get_alignment(t); - break; - } - - default: - assert_not_reached(); - } - - if (a < 0) - return a; - - assert(a > 0 && a <= 8); - if ((size_t) a > alignment) - alignment = (size_t) a; - - p += n; - } - - return alignment; -} - -int bus_gvariant_is_fixed_size(const char *signature) { - const char *p; - int r; - - assert(signature); - - p = signature; - while (*p != 0) { - size_t n; - - r = signature_element_length(p, &n); - if (r < 0) - return r; - - switch (*p) { - - case SD_BUS_TYPE_STRING: - case SD_BUS_TYPE_OBJECT_PATH: - case SD_BUS_TYPE_SIGNATURE: - case SD_BUS_TYPE_ARRAY: - case SD_BUS_TYPE_VARIANT: - return 0; - - 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_UNIX_FD: - case SD_BUS_TYPE_INT64: - case SD_BUS_TYPE_UINT64: - case SD_BUS_TYPE_DOUBLE: - break; - - case SD_BUS_TYPE_STRUCT_BEGIN: - case SD_BUS_TYPE_DICT_ENTRY_BEGIN: { - char t[n-1]; - - memcpy(t, p + 1, n - 2); - t[n - 2] = 0; - - r = bus_gvariant_is_fixed_size(t); - if (r <= 0) - return r; - break; - } - - default: - assert_not_reached(); - } - - p += n; - } - - return true; -} - -size_t bus_gvariant_determine_word_size(size_t sz, size_t extra) { - if (sz + extra <= 0xFF) - return 1; - else if (sz + extra*2 <= 0xFFFF) - return 2; - else if (sz + extra*4 <= 0xFFFFFFFF) - return 4; - else - return 8; -} - -size_t bus_gvariant_read_word_le(void *p, size_t sz) { - union { - uint16_t u16; - uint32_t u32; - uint64_t u64; - } x; - - assert(p); - - if (sz == 1) - return *(uint8_t*) p; - - memcpy(&x, p, sz); - - if (sz == 2) - return le16toh(x.u16); - else if (sz == 4) - return le32toh(x.u32); - else if (sz == 8) - return le64toh(x.u64); - - assert_not_reached(); -} - -void bus_gvariant_write_word_le(void *p, size_t sz, size_t value) { - union { - uint16_t u16; - uint32_t u32; - uint64_t u64; - } x; - - assert(p); - assert(sz == 8 || (value < (1ULL << (sz*8)))); - - if (sz == 1) { - *(uint8_t*) p = value; - return; - } else if (sz == 2) - x.u16 = htole16((uint16_t) value); - else if (sz == 4) - x.u32 = htole32((uint32_t) value); - else if (sz == 8) - x.u64 = htole64((uint64_t) value); - else - assert_not_reached(); - - memcpy(p, &x, sz); -} diff --git a/src/libsystemd/sd-bus/bus-gvariant.h b/src/libsystemd/sd-bus/bus-gvariant.h deleted file mode 100644 index 213fa97083e..00000000000 --- a/src/libsystemd/sd-bus/bus-gvariant.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ -#pragma once - -#include "macro.h" - -int bus_gvariant_get_size(const char *signature) _pure_; -int bus_gvariant_get_alignment(const char *signature) _pure_; -int bus_gvariant_is_fixed_size(const char *signature) _pure_; - -size_t bus_gvariant_determine_word_size(size_t sz, size_t extra); -void bus_gvariant_write_word_le(void *p, size_t sz, size_t value); -size_t bus_gvariant_read_word_le(void *p, size_t sz); diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 026ec101e3a..7ab1de80d91 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -7,7 +7,6 @@ #include "sd-bus.h" #include "alloc-util.h" -#include "bus-gvariant.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-signature.h" @@ -22,6 +21,7 @@ #include "utf8.h" static int message_append_basic(sd_bus_message *m, char type, const void *p, const void **stored); +static int message_parse_fields(sd_bus_message *m); static void *adjust_pointer(const void *p, void *old_base, size_t sz, void *new_base) { @@ -103,7 +103,6 @@ static void message_free_last_container(sd_bus_message *m) { free(c->signature); free(c->peeked_signature); - free(c->offsets); /* Move to previous container, but not if we are on root container */ if (m->n_containers > 0) @@ -147,7 +146,7 @@ static sd_bus_message* message_free(sd_bus_message *m) { return mfree(m); } -static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) { +static void *message_extend_fields(sd_bus_message *m, size_t sz, bool add_offset) { void *op, *np; size_t old_size, new_size, start; @@ -157,7 +156,7 @@ static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, b return NULL; old_size = sizeof(struct bus_header) + m->fields_size; - start = ALIGN_TO(old_size, align); + start = ALIGN8(old_size); new_size = start + sz; if (new_size < start || new_size > UINT32_MAX) @@ -226,51 +225,32 @@ static int message_append_field_string( assert(m); - /* dbus1 only allows 8bit header field ids */ + /* dbus only allows 8bit header field ids */ if (h > 0xFF) return -EINVAL; - /* dbus1 doesn't allow strings over 32bit, let's enforce this - * globally, to not risk convertability */ + /* dbus doesn't allow strings over 32bit */ l = strlen(s); if (l > UINT32_MAX) return -EINVAL; /* Signature "(yv)" where the variant contains "s" */ - if (BUS_MESSAGE_IS_GVARIANT(m)) { + /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */ + p = message_extend_fields(m, 4 + 4 + l + 1, false); + if (!p) + return -ENOMEM; - /* (field id 64bit, ((string + NUL) + NUL + signature string 's') */ - p = message_extend_fields(m, 8, 8 + l + 1 + 1 + 1, true); - if (!p) - return -ENOMEM; + p[0] = (uint8_t) h; + p[1] = 1; + p[2] = type; + p[3] = 0; - *((uint64_t*) p) = h; - memcpy(p+8, s, l); - p[8+l] = 0; - p[8+l+1] = 0; - p[8+l+2] = type; + ((uint32_t*) p)[1] = l; + memcpy(p + 8, s, l + 1); - if (ret) - *ret = (char*) p + 8; - - } else { - /* (field id byte + (signature length + signature 's' + NUL) + (string length + string + NUL)) */ - p = message_extend_fields(m, 8, 4 + 4 + l + 1, false); - if (!p) - return -ENOMEM; - - p[0] = (uint8_t) h; - p[1] = 1; - p[2] = type; - p[3] = 0; - - ((uint32_t*) p)[1] = l; - memcpy(p + 8, s, l + 1); - - if (ret) - *ret = (char*) p + 8; - } + if (ret) + *ret = (char*) p + 8; return 0; } @@ -286,37 +266,31 @@ static int message_append_field_signature( assert(m); - /* dbus1 only allows 8bit header field ids */ + /* dbus only allows 8bit header field ids */ if (h > 0xFF) return -EINVAL; - /* dbus1 doesn't allow signatures over 8bit, let's enforce - * this globally, to not risk convertability */ + /* dbus doesn't allow signatures over 8bit */ l = strlen(s); if (l > SD_BUS_MAXIMUM_SIGNATURE_LENGTH) return -EINVAL; /* Signature "(yv)" where the variant contains "g" */ - if (BUS_MESSAGE_IS_GVARIANT(m)) - /* For gvariant the serialization is the same as for normal strings */ - return message_append_field_string(m, h, 'g', s, ret); - else { - /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */ - p = message_extend_fields(m, 8, 4 + 1 + l + 1, false); - if (!p) - return -ENOMEM; + /* (field id byte + (signature length + signature 'g' + NUL) + (string length + string + NUL)) */ + p = message_extend_fields(m, 4 + 1 + l + 1, false); + if (!p) + return -ENOMEM; - p[0] = (uint8_t) h; - p[1] = 1; - p[2] = SD_BUS_TYPE_SIGNATURE; - p[3] = 0; - p[4] = l; - memcpy(p + 5, s, l + 1); + p[0] = (uint8_t) h; + p[1] = 1; + p[2] = SD_BUS_TYPE_SIGNATURE; + p[3] = 0; + p[4] = l; + memcpy(p + 5, s, l + 1); - if (ret) - *ret = (const char*) p + 5; - } + if (ret) + *ret = (const char*) p + 5; return 0; } @@ -326,75 +300,21 @@ static int message_append_field_uint32(sd_bus_message *m, uint64_t h, uint32_t x assert(m); - /* dbus1 only allows 8bit header field ids */ + /* dbus only allows 8bit header field ids */ if (h > 0xFF) return -EINVAL; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - /* (field id 64bit + ((value + NUL + signature string 'u') */ + /* (field id byte + (signature length + signature 'u' + NUL) + value) */ + p = message_extend_fields(m, 4 + 4, false); + if (!p) + return -ENOMEM; - p = message_extend_fields(m, 8, 8 + 4 + 1 + 1, true); - if (!p) - return -ENOMEM; + p[0] = (uint8_t) h; + p[1] = 1; + p[2] = 'u'; + p[3] = 0; - *((uint64_t*) p) = h; - *((uint32_t*) (p + 8)) = x; - p[12] = 0; - p[13] = 'u'; - } else { - /* (field id byte + (signature length + signature 'u' + NUL) + value) */ - p = message_extend_fields(m, 8, 4 + 4, false); - if (!p) - return -ENOMEM; - - p[0] = (uint8_t) h; - p[1] = 1; - p[2] = 'u'; - p[3] = 0; - - ((uint32_t*) p)[1] = x; - } - - return 0; -} - -static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x) { - uint8_t *p; - - assert(m); - - /* dbus1 only allows 8bit header field ids */ - if (h > 0xFF) - return -EINVAL; - - if (BUS_MESSAGE_IS_GVARIANT(m)) { - /* (field id 64bit + ((value + NUL + signature string 't') */ - - p = message_extend_fields(m, 8, 8 + 8 + 1 + 1, true); - if (!p) - return -ENOMEM; - - *((uint64_t*) p) = h; - *((uint64_t*) (p + 8)) = x; - p[16] = 0; - p[17] = 't'; - } else { - /* (field id byte + (signature length + signature 't' + NUL) + 4 byte padding + value) */ - p = message_extend_fields(m, 8, 4 + 4 + 8, false); - if (!p) - return -ENOMEM; - - p[0] = (uint8_t) h; - p[1] = 1; - p[2] = 't'; - p[3] = 0; - p[4] = 0; - p[5] = 0; - p[6] = 0; - p[7] = 0; - - ((uint64_t*) p)[1] = x; - } + ((uint32_t*) p)[1] = x; return 0; } @@ -402,28 +322,20 @@ static int message_append_field_uint64(sd_bus_message *m, uint64_t h, uint64_t x static int message_append_reply_cookie(sd_bus_message *m, uint64_t cookie) { assert(m); - if (BUS_MESSAGE_IS_GVARIANT(m)) - return message_append_field_uint64(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, cookie); - else { - /* 64bit cookies are not supported on dbus1 */ - if (cookie > 0xffffffffUL) - return -EOPNOTSUPP; + /* 64bit cookies are not supported */ + if (cookie > UINT32_MAX) + return -EOPNOTSUPP; - return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie); - } + return message_append_field_uint32(m, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) cookie); } -int bus_message_from_header( +static int message_from_header( sd_bus *bus, - void *header, - size_t header_accessible, - void *footer, - size_t footer_accessible, + void *buffer, size_t message_size, int *fds, size_t n_fds, const char *label, - size_t extra, sd_bus_message **ret) { _cleanup_free_ sd_bus_message *m = NULL; @@ -431,20 +343,14 @@ int bus_message_from_header( size_t a, label_sz = 0; /* avoid false maybe-uninitialized warning */ assert(bus); - assert(header || header_accessible <= 0); - assert(footer || footer_accessible <= 0); + assert(buffer || message_size <= 0); assert(fds || n_fds <= 0); assert(ret); - if (header_accessible < sizeof(struct bus_header)) + if (message_size < sizeof(struct bus_header)) return -EBADMSG; - if (header_accessible > message_size) - return -EBADMSG; - if (footer_accessible > message_size) - return -EBADMSG; - - h = header; + h = buffer; if (!IN_SET(h->version, 1, 2)) return -EBADMSG; @@ -456,7 +362,7 @@ int bus_message_from_header( /* Note that we are happy with unknown flags in the flags header! */ - a = ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); + a = ALIGN(sizeof(sd_bus_message)); if (label) { label_sz = strlen(label); @@ -468,56 +374,24 @@ int bus_message_from_header( return -ENOMEM; m->sealed = true; - m->header = header; - m->header_accessible = header_accessible; - m->footer = footer; - m->footer_accessible = footer_accessible; + m->header = buffer; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - size_t ws; + if (h->serial == 0) + return -EBADMSG; - if (h->dbus2.cookie == 0) - return -EBADMSG; + m->fields_size = BUS_MESSAGE_BSWAP32(m, h->fields_size); + m->body_size = BUS_MESSAGE_BSWAP32(m, h->body_size); - /* dbus2 derives the sizes from the message size and - the offset table at the end, since it is formatted as - gvariant "yyyyuta{tv}v". Since the message itself is a - structure with precisely to variable sized entries, - there's only one offset in the table, which marks the - end of the fields array. */ - - ws = bus_gvariant_determine_word_size(message_size, 0); - if (footer_accessible < ws) - return -EBADMSG; - - m->fields_size = bus_gvariant_read_word_le((uint8_t*) footer + footer_accessible - ws, ws); - if (ALIGN8(m->fields_size) > message_size - ws) - return -EBADMSG; - if (m->fields_size < sizeof(struct bus_header)) - return -EBADMSG; - - m->fields_size -= sizeof(struct bus_header); - m->body_size = message_size - (sizeof(struct bus_header) + ALIGN8(m->fields_size)); - } else { - if (h->dbus1.serial == 0) - return -EBADMSG; - - /* dbus1 has the sizes in the header */ - m->fields_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.fields_size); - m->body_size = BUS_MESSAGE_BSWAP32(m, h->dbus1.body_size); - - assert(message_size >= sizeof(struct bus_header)); - if (m->fields_size > message_size - sizeof(struct bus_header) || - ALIGN8(m->fields_size) > message_size - sizeof(struct bus_header) || - m->body_size != message_size - sizeof(struct bus_header) - ALIGN8(m->fields_size)) - return -EBADMSG; - } + assert(message_size >= sizeof(struct bus_header)); + if (ALIGN8(m->fields_size) > message_size - sizeof(struct bus_header) || + m->body_size != message_size - sizeof(struct bus_header) - ALIGN8(m->fields_size)) + return -EBADMSG; m->fds = fds; m->n_fds = n_fds; if (label) { - m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)) + ALIGN(extra); + m->creds.label = (char*) m + ALIGN(sizeof(sd_bus_message)); memcpy(m->creds.label, label, label_sz + 1); m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; @@ -544,14 +418,12 @@ int bus_message_from_malloc( size_t sz; int r; - r = bus_message_from_header( + r = message_from_header( bus, - buffer, length, /* in this case the initial bytes and the final bytes are the same */ buffer, length, - length, fds, n_fds, label, - 0, &m); + &m); if (r < 0) return r; @@ -568,7 +440,7 @@ int bus_message_from_malloc( m->iovec = m->iovec_fixed; m->iovec[0] = IOVEC_MAKE(buffer, length); - r = bus_message_parse_fields(m); + r = message_parse_fields(m); if (r < 0) return r; @@ -603,7 +475,6 @@ _public_ int sd_bus_message_new( t->header->type = type; t->header->version = bus->message_version; t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING); - t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t); if (bus->allow_interactive_authorization) t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; @@ -1196,7 +1067,7 @@ _public_ int sd_bus_message_set_allow_interactive_authorization(sd_bus_message * return 0; } -struct bus_body_part *message_append_part(sd_bus_message *m) { +static struct bus_body_part *message_append_part(sd_bus_message *m) { struct bus_body_part *part; assert(m); @@ -1277,27 +1148,6 @@ static int part_make_space( return 0; } -static int message_add_offset(sd_bus_message *m, size_t offset) { - struct bus_container *c; - - assert(m); - assert(BUS_MESSAGE_IS_GVARIANT(m)); - - /* Add offset to current container, unless this is the first - * item in it, which will have the 0 offset, which we can - * ignore. */ - c = message_get_last_container(m); - - if (!c->need_offsets) - return 0; - - if (!GREEDY_REALLOC(c->offsets, c->n_offsets + 1)) - return -ENOMEM; - - c->offsets[c->n_offsets++] = offset; - return 0; -} - static void message_extend_containers(sd_bus_message *m, size_t expand) { assert(m); @@ -1316,9 +1166,7 @@ static void message_extend_containers(sd_bus_message *m, size_t expand) { static void *message_extend_body( sd_bus_message *m, size_t align, - size_t sz, - bool add_offset, - bool force_inline) { + size_t sz) { size_t start_body, end_body, padding, added; void *p; @@ -1331,7 +1179,7 @@ static void *message_extend_body( if (m->poisoned) return NULL; - start_body = ALIGN_TO((size_t) m->body_size, align); + start_body = ALIGN_TO(m->body_size, align); end_body = start_body + sz; padding = start_body - m->body_size; @@ -1350,8 +1198,7 @@ static void *message_extend_body( add_new_part = m->n_body_parts <= 0 || m->body_end->sealed || - (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size) || - (force_inline && m->body_end->size > MEMFD_MIN_SIZE); + (padding != ALIGN_TO(m->body_end->size, align) - m->body_end->size); /* If this must be an inlined extension, let's create a new part if * the previous part is large enough to be inlined. */ @@ -1405,14 +1252,6 @@ static void *message_extend_body( m->body_size = end_body; message_extend_containers(m, added); - if (add_offset) { - r = message_add_offset(m, end_body); - if (r < 0) { - m->poisoned = true; - return NULL; - } - } - return p; } @@ -1449,6 +1288,7 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void _cleanup_close_ int fd = -1; struct bus_container *c; ssize_t align, sz; + uint32_t u32; void *a; assert_return(m, -EINVAL); @@ -1477,149 +1317,85 @@ int message_append_basic(sd_bus_message *m, char type, const void *p, const void } } - if (BUS_MESSAGE_IS_GVARIANT(m)) { - uint8_t u8; - uint32_t u32; + switch (type) { - switch (type) { + case SD_BUS_TYPE_STRING: + /* To make things easy we'll serialize a NULL string + * into the empty string */ + p = strempty(p); - case SD_BUS_TYPE_SIGNATURE: - case SD_BUS_TYPE_STRING: - p = strempty(p); + _fallthrough_; + case SD_BUS_TYPE_OBJECT_PATH: - _fallthrough_; - case SD_BUS_TYPE_OBJECT_PATH: - if (!p) - return -EINVAL; + if (!p) + return -EINVAL; - align = 1; - sz = strlen(p) + 1; - break; + align = 4; + sz = 4 + strlen(p) + 1; + break; - case SD_BUS_TYPE_BOOLEAN: + case SD_BUS_TYPE_SIGNATURE: - u8 = p && *(int*) p; - p = &u8; + p = strempty(p); - align = sz = 1; - break; + align = 1; + sz = 1 + strlen(p) + 1; + break; - case SD_BUS_TYPE_UNIX_FD: + case SD_BUS_TYPE_BOOLEAN: - if (!p) - return -EINVAL; + u32 = p && *(int*) p; + p = &u32; - fd = message_push_fd(m, *(int*) p); - if (fd < 0) - return fd; + align = sz = 4; + break; - u32 = m->n_fds; - p = &u32; + case SD_BUS_TYPE_UNIX_FD: - align = sz = 4; - break; + if (!p) + return -EINVAL; - default: - align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); - sz = bus_gvariant_get_size(CHAR_TO_STR(type)); - break; - } + fd = message_push_fd(m, *(int*) p); + if (fd < 0) + return fd; - assert(align > 0); - assert(sz > 0); + u32 = m->n_fds; + p = &u32; - a = message_extend_body(m, align, sz, true, false); - if (!a) - return -ENOMEM; + align = sz = 4; + break; + default: + align = bus_type_get_alignment(type); + sz = bus_type_get_size(type); + break; + } + + assert(align > 0); + assert(sz > 0); + + a = message_extend_body(m, align, sz); + if (!a) + return -ENOMEM; + + if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { + *(uint32_t*) a = sz - 5; + memcpy((uint8_t*) a + 4, p, sz - 4); + + if (stored) + *stored = (const uint8_t*) a + 4; + + } else if (type == SD_BUS_TYPE_SIGNATURE) { + *(uint8_t*) a = sz - 2; + memcpy((uint8_t*) a + 1, p, sz - 1); + + if (stored) + *stored = (const uint8_t*) a + 1; + } else { memcpy(a, p, sz); if (stored) - *stored = (const uint8_t*) a; - - } else { - uint32_t u32; - - switch (type) { - - case SD_BUS_TYPE_STRING: - /* To make things easy we'll serialize a NULL string - * into the empty string */ - p = strempty(p); - - _fallthrough_; - case SD_BUS_TYPE_OBJECT_PATH: - - if (!p) - return -EINVAL; - - align = 4; - sz = 4 + strlen(p) + 1; - break; - - case SD_BUS_TYPE_SIGNATURE: - - p = strempty(p); - - align = 1; - sz = 1 + strlen(p) + 1; - break; - - case SD_BUS_TYPE_BOOLEAN: - - u32 = p && *(int*) p; - p = &u32; - - align = sz = 4; - break; - - case SD_BUS_TYPE_UNIX_FD: - - if (!p) - return -EINVAL; - - fd = message_push_fd(m, *(int*) p); - if (fd < 0) - return fd; - - u32 = m->n_fds; - p = &u32; - - align = sz = 4; - break; - - default: - align = bus_type_get_alignment(type); - sz = bus_type_get_size(type); - break; - } - - assert(align > 0); - assert(sz > 0); - - a = message_extend_body(m, align, sz, false, false); - if (!a) - return -ENOMEM; - - if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { - *(uint32_t*) a = sz - 5; - memcpy((uint8_t*) a + 4, p, sz - 4); - - if (stored) - *stored = (const uint8_t*) a + 4; - - } else if (type == SD_BUS_TYPE_SIGNATURE) { - *(uint8_t*) a = sz - 2; - memcpy((uint8_t*) a + 1, p, sz - 1); - - if (stored) - *stored = (const uint8_t*) a + 1; - } else { - memcpy(a, p, sz); - - if (stored) - *stored = a; - } + *stored = a; } if (type == SD_BUS_TYPE_UNIX_FD) @@ -1670,20 +1446,12 @@ _public_ int sd_bus_message_append_string_space( } } - if (BUS_MESSAGE_IS_GVARIANT(m)) { - a = message_extend_body(m, 1, size + 1, true, false); - if (!a) - return -ENOMEM; + a = message_extend_body(m, 4, 4 + size + 1); + if (!a) + return -ENOMEM; - *s = a; - } else { - a = message_extend_body(m, 4, 4 + size + 1, false, false); - if (!a) - return -ENOMEM; - - *(uint32_t*) a = size; - *s = (char*) a + 4; - } + *(uint32_t*) a = size; + *s = (char*) a + 4; (*s)[size] = 0; @@ -1732,18 +1500,19 @@ static int bus_message_open_array( struct bus_container *c, const char *contents, uint32_t **array_size, - size_t *begin, - bool *need_offsets) { + size_t *begin) { unsigned nindex; - int alignment, r; + int alignment; + void *a, *op; + size_t os; + struct bus_body_part *o; assert(m); assert(c); assert(contents); assert(array_size); assert(begin); - assert(need_offsets); if (!signature_is_single(contents, true)) return -EINVAL; @@ -1776,49 +1545,28 @@ static int bus_message_open_array( nindex = e - c->signature; } - if (BUS_MESSAGE_IS_GVARIANT(m)) { - alignment = bus_gvariant_get_alignment(contents); - if (alignment < 0) - return alignment; + alignment = bus_type_get_alignment(contents[0]); + if (alignment < 0) + return alignment; - /* Add alignment padding and add to offset list */ - if (!message_extend_body(m, alignment, 0, false, false)) - return -ENOMEM; + a = message_extend_body(m, 4, 4); + if (!a) + return -ENOMEM; - r = bus_gvariant_is_fixed_size(contents); - if (r < 0) - return r; + o = m->body_end; + op = m->body_end->data; + os = m->body_end->size; - *begin = m->body_size; - *need_offsets = r == 0; - } else { - void *a, *op; - size_t os; - struct bus_body_part *o; + /* Add alignment between size and first element */ + if (!message_extend_body(m, alignment, 0)) + return -ENOMEM; - alignment = bus_type_get_alignment(contents[0]); - if (alignment < 0) - return alignment; + /* location of array size might have changed so let's readjust a */ + if (o == m->body_end) + a = adjust_pointer(a, op, os, m->body_end->data); - a = message_extend_body(m, 4, 4, false, false); - if (!a) - return -ENOMEM; - - o = m->body_end; - op = m->body_end->data; - os = m->body_end->size; - - /* Add alignment between size and first element */ - if (!message_extend_body(m, alignment, 0, false, false)) - return -ENOMEM; - - /* location of array size might have changed so let's readjust a */ - if (o == m->body_end) - a = adjust_pointer(a, op, os, m->body_end->data); - - *(uint32_t*) a = 0; - *array_size = a; - } + *(uint32_t*) a = 0; + *array_size = a; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index = nindex; @@ -1831,6 +1579,9 @@ static int bus_message_open_variant( struct bus_container *c, const char *contents) { + size_t l; + void *a; + assert(m); assert(c); assert(contents); @@ -1859,24 +1610,13 @@ static int bus_message_open_variant( } } - if (BUS_MESSAGE_IS_GVARIANT(m)) { - /* Variants are always aligned to 8 */ + l = strlen(contents); + a = message_extend_body(m, 1, 1 + l + 1); + if (!a) + return -ENOMEM; - if (!message_extend_body(m, 8, 0, false, false)) - return -ENOMEM; - - } else { - size_t l; - void *a; - - l = strlen(contents); - a = message_extend_body(m, 1, 1 + l + 1, false, false); - if (!a) - return -ENOMEM; - - *(uint8_t*) a = l; - memcpy((uint8_t*) a + 1, contents, l + 1); - } + *(uint8_t*) a = l; + memcpy((uint8_t*) a + 1, contents, l + 1); if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; @@ -1888,17 +1628,14 @@ static int bus_message_open_struct( sd_bus_message *m, struct bus_container *c, const char *contents, - size_t *begin, - bool *need_offsets) { + size_t *begin) { size_t nindex; - int r; assert(m); assert(c); assert(contents); assert(begin); - assert(need_offsets); if (!signature_is_valid(contents, false)) return -EINVAL; @@ -1929,27 +1666,9 @@ static int bus_message_open_struct( nindex = e - c->signature; } - if (BUS_MESSAGE_IS_GVARIANT(m)) { - int alignment; - - alignment = bus_gvariant_get_alignment(contents); - if (alignment < 0) - return alignment; - - if (!message_extend_body(m, alignment, 0, false, false)) - return -ENOMEM; - - r = bus_gvariant_is_fixed_size(contents); - if (r < 0) - return r; - - *begin = m->body_size; - *need_offsets = r == 0; - } else { - /* Align contents to 8 byte boundary */ - if (!message_extend_body(m, 8, 0, false, false)) - return -ENOMEM; - } + /* Align contents to 8 byte boundary */ + if (!message_extend_body(m, 8, 0)) + return -ENOMEM; if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index = nindex; @@ -1961,16 +1680,12 @@ static int bus_message_open_dict_entry( sd_bus_message *m, struct bus_container *c, const char *contents, - size_t *begin, - bool *need_offsets) { - - int r; + size_t *begin) { assert(m); assert(c); assert(contents); assert(begin); - assert(need_offsets); if (!signature_is_pair(contents)) return -EINVAL; @@ -1990,27 +1705,9 @@ static int bus_message_open_dict_entry( } else return -ENXIO; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - int alignment; - - alignment = bus_gvariant_get_alignment(contents); - if (alignment < 0) - return alignment; - - if (!message_extend_body(m, alignment, 0, false, false)) - return -ENOMEM; - - r = bus_gvariant_is_fixed_size(contents); - if (r < 0) - return r; - - *begin = m->body_size; - *need_offsets = r == 0; - } else { - /* Align contents to 8 byte boundary */ - if (!message_extend_body(m, 8, 0, false, false)) - return -ENOMEM; - } + /* Align contents to 8 byte boundary */ + if (!message_extend_body(m, 8, 0)) + return -ENOMEM; return 0; } @@ -2024,7 +1721,6 @@ _public_ int sd_bus_message_open_container( uint32_t *array_size = NULL; _cleanup_free_ char *signature = NULL; size_t before, begin = 0; - bool need_offsets = false; int r; assert_return(m, -EINVAL); @@ -2052,13 +1748,13 @@ _public_ int sd_bus_message_open_container( before = m->body_size; if (type == SD_BUS_TYPE_ARRAY) - r = bus_message_open_array(m, c, contents, &array_size, &begin, &need_offsets); + r = bus_message_open_array(m, c, contents, &array_size, &begin); else if (type == SD_BUS_TYPE_VARIANT) r = bus_message_open_variant(m, c, contents); else if (type == SD_BUS_TYPE_STRUCT) - r = bus_message_open_struct(m, c, contents, &begin, &need_offsets); + r = bus_message_open_struct(m, c, contents, &begin); else if (type == SD_BUS_TYPE_DICT_ENTRY) - r = bus_message_open_dict_entry(m, c, contents, &begin, &need_offsets); + r = bus_message_open_dict_entry(m, c, contents, &begin); else r = -EINVAL; if (r < 0) @@ -2071,192 +1767,13 @@ _public_ int sd_bus_message_open_container( .array_size = array_size, .before = before, .begin = begin, - .need_offsets = need_offsets, }; return 0; } -static int bus_message_close_array(sd_bus_message *m, struct bus_container *c) { - - assert(m); - assert(c); - - if (!BUS_MESSAGE_IS_GVARIANT(m)) - return 0; - - if (c->need_offsets) { - size_t payload, sz, i; - uint8_t *a; - - /* Variable-width arrays */ - - payload = c->n_offsets > 0 ? c->offsets[c->n_offsets-1] - c->begin : 0; - sz = bus_gvariant_determine_word_size(payload, c->n_offsets); - - a = message_extend_body(m, 1, sz * c->n_offsets, true, false); - if (!a) - return -ENOMEM; - - for (i = 0; i < c->n_offsets; i++) - bus_gvariant_write_word_le(a + sz*i, sz, c->offsets[i] - c->begin); - } else { - void *a; - - /* Fixed-width or empty arrays */ - - a = message_extend_body(m, 1, 0, true, false); /* let's add offset to parent */ - if (!a) - return -ENOMEM; - } - - return 0; -} - -static int bus_message_close_variant(sd_bus_message *m, struct bus_container *c) { - uint8_t *a; - size_t l; - - assert(m); - assert(c); - assert(c->signature); - - if (!BUS_MESSAGE_IS_GVARIANT(m)) - return 0; - - l = strlen(c->signature); - - a = message_extend_body(m, 1, 1 + l, true, false); - if (!a) - return -ENOMEM; - - a[0] = 0; - memcpy(a+1, c->signature, l); - - return 0; -} - -static int bus_message_close_struct(sd_bus_message *m, struct bus_container *c, bool add_offset) { - bool fixed_size = true; - size_t n_variable = 0; - unsigned i = 0; - const char *p; - uint8_t *a; - int r; - - assert(m); - assert(c); - - if (!BUS_MESSAGE_IS_GVARIANT(m)) - return 0; - - p = strempty(c->signature); - while (*p != 0) { - size_t n; - - r = signature_element_length(p, &n); - if (r < 0) - return r; - else { - char t[n+1]; - - memcpy(t, p, n); - t[n] = 0; - - r = bus_gvariant_is_fixed_size(t); - if (r < 0) - return r; - } - - assert(!c->need_offsets || i <= c->n_offsets); - - /* We need to add an offset for each item that has a - * variable size and that is not the last one in the - * list */ - if (r == 0) - fixed_size = false; - if (r == 0 && p[n] != 0) - n_variable++; - - i++; - p += n; - } - - assert(!c->need_offsets || i == c->n_offsets); - assert(c->need_offsets || n_variable == 0); - - if (isempty(c->signature)) { - /* The unary type is encoded as fixed 1 byte padding */ - a = message_extend_body(m, 1, 1, add_offset, false); - if (!a) - return -ENOMEM; - - *a = 0; - } else if (n_variable <= 0) { - int alignment = 1; - - /* Structures with fixed-size members only have to be - * fixed-size themselves. But gvariant requires all fixed-size - * elements to be sized a multiple of their alignment. Hence, - * we must *always* add final padding after the last member so - * the overall size of the structure is properly aligned. */ - if (fixed_size) - alignment = bus_gvariant_get_alignment(strempty(c->signature)); - - assert(alignment > 0); - - a = message_extend_body(m, alignment, 0, add_offset, false); - if (!a) - return -ENOMEM; - } else { - size_t sz; - unsigned j; - - assert(c->offsets[c->n_offsets-1] == m->body_size); - - sz = bus_gvariant_determine_word_size(m->body_size - c->begin, n_variable); - - a = message_extend_body(m, 1, sz * n_variable, add_offset, false); - if (!a) - return -ENOMEM; - - p = strempty(c->signature); - for (i = 0, j = 0; i < c->n_offsets; i++) { - unsigned k; - size_t n; - - r = signature_element_length(p, &n); - if (r < 0) - return r; - else { - char t[n+1]; - - memcpy(t, p, n); - t[n] = 0; - - p += n; - - r = bus_gvariant_is_fixed_size(t); - if (r < 0) - return r; - if (r > 0 || p[0] == 0) - continue; - } - - k = n_variable - 1 - j; - - bus_gvariant_write_word_le(a + k * sz, sz, c->offsets[i] - c->begin); - - j++; - } - } - - return 0; -} - _public_ int sd_bus_message_close_container(sd_bus_message *m) { struct bus_container *c; - int r; assert_return(m, -EINVAL); assert_return(!m->sealed, -EPERM); @@ -2271,19 +1788,9 @@ _public_ int sd_bus_message_close_container(sd_bus_message *m) { m->n_containers--; - if (c->enclosing == SD_BUS_TYPE_ARRAY) - r = bus_message_close_array(m, c); - else if (c->enclosing == SD_BUS_TYPE_VARIANT) - r = bus_message_close_variant(m, c); - else if (IN_SET(c->enclosing, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) - r = bus_message_close_struct(m, c, true); - else - assert_not_reached(); - free(c->signature); - free(c->offsets); - return r; + return 0; } typedef struct { @@ -2556,8 +2063,6 @@ _public_ int sd_bus_message_append_array_space( assert_return(ptr || size == 0, -EINVAL); assert_return(!m->poisoned, -ESTALE); - /* alignment and size of the trivial types (except bool) is - * identical for gvariant and dbus1 marshalling */ align = bus_type_get_alignment(type); sz = bus_type_get_size(type); @@ -2571,7 +2076,7 @@ _public_ int sd_bus_message_append_array_space( if (r < 0) return r; - a = message_extend_body(m, align, size, false, false); + a = message_extend_body(m, align, size); if (!a) return -ENOMEM; @@ -2699,7 +2204,7 @@ _public_ int sd_bus_message_append_array_memfd( if (r < 0) return r; - a = message_extend_body(m, align, 0, false, false); + a = message_extend_body(m, align, 0); if (!a) return -ENOMEM; @@ -2782,13 +2287,11 @@ _public_ int sd_bus_message_append_string_memfd( } } - if (!BUS_MESSAGE_IS_GVARIANT(m)) { - a = message_extend_body(m, 4, 4, false, false); - if (!a) - return -ENOMEM; + a = message_extend_body(m, 4, 4); + if (!a) + return -ENOMEM; - *(uint32_t*) a = size - 1; - } + *(uint32_t*) a = size - 1; part = message_append_part(m); if (!part) @@ -2803,14 +2306,6 @@ _public_ int sd_bus_message_append_string_memfd( m->body_size += size; message_extend_containers(m, size); - if (BUS_MESSAGE_IS_GVARIANT(m)) { - r = message_add_offset(m, m->body_size); - if (r < 0) { - m->poisoned = true; - return -ENOMEM; - } - } - if (c->enclosing != SD_BUS_TYPE_ARRAY) c->index++; @@ -2838,61 +2333,14 @@ _public_ int sd_bus_message_append_strv(sd_bus_message *m, char **l) { } static int bus_message_close_header(sd_bus_message *m) { - assert(m); - /* The actual user data is finished now, we just complete the - variant and struct now (at least on gvariant). Remember - this position, so that during parsing we know where to - put the outer container end. */ + /* The actual user data is finished now, we just complete the variant and struct now. Remember + * this position, so that during parsing we know where to put the outer container end. */ m->user_body_size = m->body_size; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - const char *signature; - size_t sz, l; - void *d; - - /* Add offset table to end of fields array */ - if (m->n_header_offsets >= 1) { - uint8_t *a; - unsigned i; - - assert(m->fields_size == m->header_offsets[m->n_header_offsets-1]); - - sz = bus_gvariant_determine_word_size(m->fields_size, m->n_header_offsets); - a = message_extend_fields(m, 1, sz * m->n_header_offsets, false); - if (!a) - return -ENOMEM; - - for (i = 0; i < m->n_header_offsets; i++) - bus_gvariant_write_word_le(a + sz*i, sz, m->header_offsets[i]); - } - - /* Add gvariant NUL byte plus signature to the end of - * the body, followed by the final offset pointing to - * the end of the fields array */ - - signature = strempty(m->root_container.signature); - l = strlen(signature); - - sz = bus_gvariant_determine_word_size(sizeof(struct bus_header) + ALIGN8(m->fields_size) + m->body_size + 1 + l + 2, 1); - d = message_extend_body(m, 1, 1 + l + 2 + sz, false, true); - if (!d) - return -ENOMEM; - - *(uint8_t*) d = 0; - *((uint8_t*) d + 1) = SD_BUS_TYPE_STRUCT_BEGIN; - memcpy((uint8_t*) d + 2, signature, l); - *((uint8_t*) d + 1 + l + 1) = SD_BUS_TYPE_STRUCT_END; - - bus_gvariant_write_word_le((uint8_t*) d + 1 + l + 2, sz, sizeof(struct bus_header) + m->fields_size); - - m->footer = d; - m->footer_accessible = 1 + l + 2 + sz; - } else { - m->header->dbus1.fields_size = m->fields_size; - m->header->dbus1.body_size = m->body_size; - } + m->header->fields_size = m->fields_size; + m->header->body_size = m->body_size; return 0; } @@ -2914,8 +2362,7 @@ _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t ti if (m->poisoned) return -ESTALE; - if (cookie > 0xffffffffULL && - !BUS_MESSAGE_IS_GVARIANT(m)) + if (cookie > UINT32_MAX) return -EOPNOTSUPP; /* In vtables the return signature of method calls is listed, @@ -2925,14 +2372,8 @@ _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t ti !streq(strempty(m->root_container.signature), m->enforced_reply_signature)) return -ENOMSG; - /* If gvariant marshalling is used we need to close the body structure */ - r = bus_message_close_struct(m, &m->root_container, false); - if (r < 0) - return r; - - /* If there's a non-trivial signature set, then add it in - * here, but only on dbus1 */ - if (!isempty(m->root_container.signature) && !BUS_MESSAGE_IS_GVARIANT(m)) { + /* If there's a non-trivial signature set, then add it in here */ + if (!isempty(m->root_container.signature)) { r = message_append_field_signature(m, BUS_MESSAGE_HEADER_SIGNATURE, m->root_container.signature, NULL); if (r < 0) return r; @@ -2948,10 +2389,7 @@ _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t ti if (r < 0) return r; - if (BUS_MESSAGE_IS_GVARIANT(m)) - m->header->dbus2.cookie = cookie; - else - m->header->dbus1.serial = (uint32_t) cookie; + m->header->serial = (uint32_t) cookie; m->timeout = m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED ? 0 : timeout_usec; @@ -2993,8 +2431,6 @@ _public_ int sd_bus_message_seal(sd_bus_message *m, uint64_t cookie, uint64_t ti m->root_container.end = m->user_body_size; m->root_container.index = 0; - m->root_container.offset_index = 0; - m->root_container.item_size = m->root_container.n_offsets > 0 ? m->root_container.offsets[0] : 0; m->sealed = true; @@ -3064,37 +2500,6 @@ void bus_body_part_unmap(struct bus_body_part *part) { return; } -static int buffer_peek(const void *p, size_t sz, size_t *rindex, size_t align, size_t nbytes, void **r) { - size_t k, start, end; - - assert(rindex); - assert(align > 0); - - start = ALIGN_TO(*rindex, align); - if (start > sz) - return -EBADMSG; - - /* Avoid overflow below */ - if (nbytes > SIZE_MAX - start) - return -EBADMSG; - - end = start + nbytes; - if (end > sz) - return -EBADMSG; - - /* Verify that padding is 0 */ - for (k = *rindex; k < start; k++) - if (((const uint8_t*) p)[k] != 0) - return -EBADMSG; - - if (r) - *r = (uint8_t*) p + start; - - *rindex = end; - - return 1; -} - static bool message_end_of_signature(sd_bus_message *m) { struct bus_container *c; @@ -3113,12 +2518,8 @@ static bool message_end_of_array(sd_bus_message *m, size_t index) { if (c->enclosing != SD_BUS_TYPE_ARRAY) return false; - if (BUS_MESSAGE_IS_GVARIANT(m)) - return index >= c->end; - else { - assert(c->array_size); - return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size); - } + assert(c->array_size); + return index >= c->begin + BUS_MESSAGE_BSWAP32(m, *c->array_size); } _public_ int sd_bus_message_at_end(sd_bus_message *m, int complete) { @@ -3179,93 +2580,6 @@ static struct bus_body_part* find_part(sd_bus_message *m, size_t index, size_t s return NULL; } -static int container_next_item(sd_bus_message *m, struct bus_container *c, size_t *rindex) { - int r; - - assert(m); - assert(c); - assert(rindex); - - if (!BUS_MESSAGE_IS_GVARIANT(m)) - return 0; - - if (c->enclosing == SD_BUS_TYPE_ARRAY) { - int sz; - - sz = bus_gvariant_get_size(c->signature); - if (sz == 0) - return -EBADMSG; - if (sz < 0) { - int alignment; - - if (c->offset_index+1 >= c->n_offsets) - goto end; - - /* Variable-size array */ - - alignment = bus_gvariant_get_alignment(c->signature); - assert(alignment > 0); - - *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); - assert(c->offsets[c->offset_index+1] >= *rindex); - c->item_size = c->offsets[c->offset_index+1] - *rindex; - } else { - - if (c->offset_index+1 >= (c->end-c->begin)/sz) - goto end; - - /* Fixed-size array */ - *rindex = c->begin + (c->offset_index+1) * sz; - c->item_size = sz; - } - - c->offset_index++; - - } else if (IN_SET(c->enclosing, 0, SD_BUS_TYPE_STRUCT, SD_BUS_TYPE_DICT_ENTRY)) { - - int alignment; - size_t n, j; - - if (c->offset_index+1 >= c->n_offsets) - goto end; - - r = signature_element_length(c->signature + c->index, &n); - if (r < 0) - return r; - - r = signature_element_length(c->signature + c->index + n, &j); - if (r < 0) - return r; - else { - char t[j+1]; - memcpy(t, c->signature + c->index + n, j); - t[j] = 0; - - alignment = bus_gvariant_get_alignment(t); - } - - assert(alignment > 0); - - *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment); - assert(c->offsets[c->offset_index+1] >= *rindex); - c->item_size = c->offsets[c->offset_index+1] - *rindex; - - c->offset_index++; - - } else if (c->enclosing == SD_BUS_TYPE_VARIANT) - goto end; - else - assert_not_reached(); - - return 0; - -end: - /* Reached the end */ - *rindex = c->end; - c->item_size = 0; - return 0; -} - static int message_peek_body( sd_bus_message *m, size_t *rindex, @@ -3388,401 +2702,36 @@ _public_ int sd_bus_message_read_basic(sd_bus_message *m, char type, void *p) { rindex = m->rindex; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - - if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) { - bool ok; - - /* D-Bus spec: The marshalling formats for the string-like types all end - * with a single zero (NUL) byte, but that byte is not considered to be part - * of the text. */ - if (c->item_size == 0) - return -EBADMSG; - - r = message_peek_body(m, &rindex, 1, c->item_size, &q); - if (r < 0) - return r; - - if (type == SD_BUS_TYPE_STRING) - ok = validate_string(q, c->item_size-1); - else if (type == SD_BUS_TYPE_OBJECT_PATH) - ok = validate_object_path(q, c->item_size-1); - else - ok = validate_signature(q, c->item_size-1); - - if (!ok) - return -EBADMSG; - - if (p) - *(const char**) p = q; - } else { - int sz, align; - - sz = bus_gvariant_get_size(CHAR_TO_STR(type)); - assert(sz > 0); - if ((size_t) sz != c->item_size) - return -EBADMSG; - - align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); - assert(align > 0); - - r = message_peek_body(m, &rindex, align, c->item_size, &q); - if (r < 0) - return r; - - switch (type) { - - case SD_BUS_TYPE_BYTE: - if (p) - *(uint8_t*) p = *(uint8_t*) q; - break; - - case SD_BUS_TYPE_BOOLEAN: - if (p) - *(int*) p = !!*(uint8_t*) q; - break; - - case SD_BUS_TYPE_INT16: - case SD_BUS_TYPE_UINT16: - if (p) - *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q); - break; - - case SD_BUS_TYPE_INT32: - case SD_BUS_TYPE_UINT32: - if (p) - *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); - break; - - case SD_BUS_TYPE_INT64: - case SD_BUS_TYPE_UINT64: - case SD_BUS_TYPE_DOUBLE: - if (p) - *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); - break; - - case SD_BUS_TYPE_UNIX_FD: { - uint32_t j; - - j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); - if (j >= m->n_fds) - return -EBADMSG; - - if (p) - *(int*) p = m->fds[j]; - - break; - } - - default: - assert_not_reached(); - } - } - - r = container_next_item(m, c, &rindex); - if (r < 0) - return r; - } else { - - if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { - uint32_t l; - bool ok; - - r = message_peek_body(m, &rindex, 4, 4, &q); - if (r < 0) - return r; - - l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); - if (l == UINT32_MAX) - /* avoid overflow right below */ - return -EBADMSG; - - r = message_peek_body(m, &rindex, 1, l+1, &q); - if (r < 0) - return r; - - if (type == SD_BUS_TYPE_OBJECT_PATH) - ok = validate_object_path(q, l); - else - ok = validate_string(q, l); - if (!ok) - return -EBADMSG; - - if (p) - *(const char**) p = q; - - } else if (type == SD_BUS_TYPE_SIGNATURE) { - uint8_t l; - - r = message_peek_body(m, &rindex, 1, 1, &q); - if (r < 0) - return r; - - l = *(uint8_t*) q; - if (l == UINT8_MAX) - /* avoid overflow right below */ - return -EBADMSG; - - r = message_peek_body(m, &rindex, 1, l+1, &q); - if (r < 0) - return r; - - if (!validate_signature(q, l)) - return -EBADMSG; - - if (p) - *(const char**) p = q; - - } else { - ssize_t sz, align; - - align = bus_type_get_alignment(type); - assert(align > 0); - - sz = bus_type_get_size(type); - assert(sz > 0); - - r = message_peek_body(m, &rindex, align, sz, &q); - if (r < 0) - return r; - - switch (type) { - - case SD_BUS_TYPE_BYTE: - if (p) - *(uint8_t*) p = *(uint8_t*) q; - break; - - case SD_BUS_TYPE_BOOLEAN: - if (p) - *(int*) p = !!*(uint32_t*) q; - break; - - case SD_BUS_TYPE_INT16: - case SD_BUS_TYPE_UINT16: - if (p) - *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q); - break; - - case SD_BUS_TYPE_INT32: - case SD_BUS_TYPE_UINT32: - if (p) - *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); - break; - - case SD_BUS_TYPE_INT64: - case SD_BUS_TYPE_UINT64: - case SD_BUS_TYPE_DOUBLE: - if (p) - *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); - break; - - case SD_BUS_TYPE_UNIX_FD: { - uint32_t j; - - j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); - if (j >= m->n_fds) - return -EBADMSG; - - if (p) - *(int*) p = m->fds[j]; - break; - } - - default: - assert_not_reached(); - } - } - } - - m->rindex = rindex; - - if (c->enclosing != SD_BUS_TYPE_ARRAY) - c->index++; - - return 1; -} - -static int bus_message_enter_array( - sd_bus_message *m, - struct bus_container *c, - const char *contents, - uint32_t **array_size, - size_t *item_size, - size_t **offsets, - size_t *n_offsets) { - - size_t rindex; - void *q; - int r; - - assert(m); - assert(c); - assert(contents); - assert(array_size); - assert(item_size); - assert(offsets); - assert(n_offsets); - - if (!signature_is_single(contents, true)) - return -EINVAL; - - if (!c->signature || c->signature[c->index] == 0) - return -ENXIO; - - if (c->signature[c->index] != SD_BUS_TYPE_ARRAY) - return -ENXIO; - - if (!startswith(c->signature + c->index + 1, contents)) - return -ENXIO; - - rindex = m->rindex; - - if (!BUS_MESSAGE_IS_GVARIANT(m)) { - /* dbus1 */ - int alignment; + if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH)) { + uint32_t l; + bool ok; r = message_peek_body(m, &rindex, 4, 4, &q); if (r < 0) return r; - if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE) + l = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + if (l == UINT32_MAX) + /* avoid overflow right below */ return -EBADMSG; - alignment = bus_type_get_alignment(contents[0]); - if (alignment < 0) - return alignment; - - r = message_peek_body(m, &rindex, alignment, 0, NULL); + r = message_peek_body(m, &rindex, 1, l+1, &q); if (r < 0) return r; - *array_size = (uint32_t*) q; - - } else if (c->item_size <= 0) { - - /* gvariant: empty array */ - *item_size = 0; - *offsets = NULL; - *n_offsets = 0; - - } else if (bus_gvariant_is_fixed_size(contents)) { - - /* gvariant: fixed length array */ - *item_size = bus_gvariant_get_size(contents); - *offsets = NULL; - *n_offsets = 0; - - } else { - size_t where, previous = 0, framing, sz; - int alignment; - unsigned i; - - /* gvariant: variable length array */ - sz = bus_gvariant_determine_word_size(c->item_size, 0); - - where = rindex + c->item_size - sz; - r = message_peek_body(m, &where, 1, sz, &q); - if (r < 0) - return r; - - framing = bus_gvariant_read_word_le(q, sz); - if (framing > c->item_size - sz) - return -EBADMSG; - if ((c->item_size - framing) % sz != 0) + if (type == SD_BUS_TYPE_OBJECT_PATH) + ok = validate_object_path(q, l); + else + ok = validate_string(q, l); + if (!ok) return -EBADMSG; - *n_offsets = (c->item_size - framing) / sz; + if (p) + *(const char**) p = q; - where = rindex + framing; - r = message_peek_body(m, &where, 1, *n_offsets * sz, &q); - if (r < 0) - return r; + } else if (type == SD_BUS_TYPE_SIGNATURE) { + uint8_t l; - *offsets = new(size_t, *n_offsets); - if (!*offsets) - return -ENOMEM; - - alignment = bus_gvariant_get_alignment(c->signature); - assert(alignment > 0); - - for (i = 0; i < *n_offsets; i++) { - size_t x, start; - - start = ALIGN_TO(previous, alignment); - - x = bus_gvariant_read_word_le((uint8_t*) q + i * sz, sz); - if (x > c->item_size - sz) - return -EBADMSG; - if (x < start) - return -EBADMSG; - - (*offsets)[i] = rindex + x; - previous = x; - } - - *item_size = (*offsets)[0] - rindex; - } - - m->rindex = rindex; - - if (c->enclosing != SD_BUS_TYPE_ARRAY) - c->index += 1 + strlen(contents); - - return 1; -} - -static int bus_message_enter_variant( - sd_bus_message *m, - struct bus_container *c, - const char *contents, - size_t *item_size) { - - size_t rindex; - uint8_t l; - void *q; - int r; - - assert(m); - assert(c); - assert(contents); - assert(item_size); - - if (!signature_is_single(contents, false)) - return -EINVAL; - - if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN) - return -EINVAL; - - if (!c->signature || c->signature[c->index] == 0) - return -ENXIO; - - if (c->signature[c->index] != SD_BUS_TYPE_VARIANT) - return -ENXIO; - - rindex = m->rindex; - - if (BUS_MESSAGE_IS_GVARIANT(m)) { - size_t k, where; - - k = strlen(contents); - if (1+k > c->item_size) - return -EBADMSG; - - where = rindex + c->item_size - (1+k); - r = message_peek_body(m, &where, 1, 1+k, &q); - if (r < 0) - return r; - - if (*(char*) q != 0) - return -EBADMSG; - - if (memcmp((uint8_t*) q+1, contents, k)) - return -ENXIO; - - *item_size = c->item_size - (1+k); - - } else { r = message_peek_body(m, &rindex, 1, 1, &q); if (r < 0) return r; @@ -3799,8 +2748,68 @@ static int bus_message_enter_variant( if (!validate_signature(q, l)) return -EBADMSG; - if (!streq(q, contents)) - return -ENXIO; + if (p) + *(const char**) p = q; + + } else { + ssize_t sz, align; + + align = bus_type_get_alignment(type); + assert(align > 0); + + sz = bus_type_get_size(type); + assert(sz > 0); + + r = message_peek_body(m, &rindex, align, sz, &q); + if (r < 0) + return r; + + switch (type) { + + case SD_BUS_TYPE_BYTE: + if (p) + *(uint8_t*) p = *(uint8_t*) q; + break; + + case SD_BUS_TYPE_BOOLEAN: + if (p) + *(int*) p = !!*(uint32_t*) q; + break; + + case SD_BUS_TYPE_INT16: + case SD_BUS_TYPE_UINT16: + if (p) + *(uint16_t*) p = BUS_MESSAGE_BSWAP16(m, *(uint16_t*) q); + break; + + case SD_BUS_TYPE_INT32: + case SD_BUS_TYPE_UINT32: + if (p) + *(uint32_t*) p = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + break; + + case SD_BUS_TYPE_INT64: + case SD_BUS_TYPE_UINT64: + case SD_BUS_TYPE_DOUBLE: + if (p) + *(uint64_t*) p = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); + break; + + case SD_BUS_TYPE_UNIX_FD: { + uint32_t j; + + j = BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q); + if (j >= m->n_fds) + return -EBADMSG; + + if (p) + *(int*) p = m->fds[j]; + break; + } + + default: + assert_not_reached(); + } } m->rindex = rindex; @@ -3811,192 +2820,119 @@ static int bus_message_enter_variant( return 1; } -static int build_struct_offsets( - sd_bus_message *m, - const char *signature, - size_t size, - size_t *item_size, - size_t **offsets, - size_t *n_offsets) { - - unsigned n_variable = 0, n_total = 0, v; - size_t previous, where; - const char *p; - size_t sz; - void *q; - int r; - - assert(m); - assert(item_size); - assert(offsets); - assert(n_offsets); - - if (isempty(signature)) { - /* Unary type is encoded as *fixed* 1 byte padding */ - r = message_peek_body(m, &m->rindex, 1, 1, &q); - if (r < 0) - return r; - - if (*(uint8_t *) q != 0) - return -EBADMSG; - - *item_size = 0; - *offsets = NULL; - *n_offsets = 0; - return 0; - } - - sz = bus_gvariant_determine_word_size(size, 0); - if (sz <= 0) - return -EBADMSG; - - /* First, loop over signature and count variable elements and - * elements in general. We use this to know how large the - * offset array is at the end of the structure. Note that - * GVariant only stores offsets for all variable size elements - * that are not the last item. */ - - p = signature; - while (*p != 0) { - size_t n; - - r = signature_element_length(p, &n); - if (r < 0) - return r; - else { - char t[n+1]; - - memcpy(t, p, n); - t[n] = 0; - - r = bus_gvariant_is_fixed_size(t); - } - - if (r < 0) - return r; - if (r == 0 && p[n] != 0) /* except the last item */ - n_variable++; - n_total++; - - p += n; - } - - if (size < n_variable * sz) - return -EBADMSG; - - where = m->rindex + size - (n_variable * sz); - r = message_peek_body(m, &where, 1, n_variable * sz, &q); - if (r < 0) - return r; - - v = n_variable; - - *offsets = new(size_t, n_total); - if (!*offsets) - return -ENOMEM; - - *n_offsets = 0; - - /* Second, loop again and build an offset table */ - p = signature; - previous = m->rindex; - while (*p != 0) { - size_t n, offset; - int k; - - r = signature_element_length(p, &n); - if (r < 0) - return r; - else { - char t[n+1]; - - memcpy(t, p, n); - t[n] = 0; - - size_t align = bus_gvariant_get_alignment(t); - assert(align > 0); - - /* The possible start of this member after including alignment */ - size_t start = ALIGN_TO(previous, align); - - k = bus_gvariant_get_size(t); - if (k < 0) { - size_t x; - - /* Variable size */ - if (v > 0) { - v--; - - x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz); - if (x >= size) - return -EBADMSG; - } else - /* The last item's end is determined - * from the start of the offset array */ - x = size - (n_variable * sz); - - offset = m->rindex + x; - if (offset < start) - return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG), - "For type %s with alignment %zu, message specifies offset %zu which is smaller than previous end %zu + alignment = %zu", - t, align, - offset, - previous, - start); - } else - /* Fixed size */ - offset = start + k; - } - - previous = (*offsets)[(*n_offsets)++] = offset; - p += n; - } - - assert(v == 0); - assert(*n_offsets == n_total); - - *item_size = (*offsets)[0] - m->rindex; - return 0; -} - -static int enter_struct_or_dict_entry( +static int bus_message_enter_array( sd_bus_message *m, struct bus_container *c, const char *contents, - size_t *item_size, - size_t **offsets, - size_t *n_offsets) { + uint32_t **array_size) { + size_t rindex; + void *q; + int alignment, r; + + assert(m); + assert(c); + assert(contents); + assert(array_size); + + if (!signature_is_single(contents, true)) + return -EINVAL; + + if (!c->signature || c->signature[c->index] == 0) + return -ENXIO; + + if (c->signature[c->index] != SD_BUS_TYPE_ARRAY) + return -ENXIO; + + if (!startswith(c->signature + c->index + 1, contents)) + return -ENXIO; + + rindex = m->rindex; + + r = message_peek_body(m, &rindex, 4, 4, &q); + if (r < 0) + return r; + + if (BUS_MESSAGE_BSWAP32(m, *(uint32_t*) q) > BUS_ARRAY_MAX_SIZE) + return -EBADMSG; + + alignment = bus_type_get_alignment(contents[0]); + if (alignment < 0) + return alignment; + + r = message_peek_body(m, &rindex, alignment, 0, NULL); + if (r < 0) + return r; + + *array_size = (uint32_t*) q; + + m->rindex = rindex; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index += 1 + strlen(contents); + + return 1; +} + +static int bus_message_enter_variant( + sd_bus_message *m, + struct bus_container *c, + const char *contents) { + + size_t rindex; + uint8_t l; + void *q; int r; assert(m); assert(c); assert(contents); - assert(item_size); - assert(offsets); - assert(n_offsets); - if (!BUS_MESSAGE_IS_GVARIANT(m)) { + if (!signature_is_single(contents, false)) + return -EINVAL; - /* dbus1 */ - r = message_peek_body(m, &m->rindex, 8, 0, NULL); - if (r < 0) - return r; + if (*contents == SD_BUS_TYPE_DICT_ENTRY_BEGIN) + return -EINVAL; - } else - /* gvariant with contents */ - return build_struct_offsets(m, contents, c->item_size, item_size, offsets, n_offsets); + if (!c->signature || c->signature[c->index] == 0) + return -ENXIO; - return 0; + if (c->signature[c->index] != SD_BUS_TYPE_VARIANT) + return -ENXIO; + + rindex = m->rindex; + + r = message_peek_body(m, &rindex, 1, 1, &q); + if (r < 0) + return r; + + l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; + + r = message_peek_body(m, &rindex, 1, l+1, &q); + if (r < 0) + return r; + + if (!validate_signature(q, l)) + return -EBADMSG; + + if (!streq(q, contents)) + return -ENXIO; + + m->rindex = rindex; + + if (c->enclosing != SD_BUS_TYPE_ARRAY) + c->index++; + + return 1; } static int bus_message_enter_struct( sd_bus_message *m, struct bus_container *c, - const char *contents, - size_t *item_size, - size_t **offsets, - size_t *n_offsets) { + const char *contents) { size_t l; int r; @@ -4004,9 +2940,6 @@ static int bus_message_enter_struct( assert(m); assert(c); assert(contents); - assert(item_size); - assert(offsets); - assert(n_offsets); if (!signature_is_valid(contents, false)) return -EINVAL; @@ -4021,7 +2954,7 @@ static int bus_message_enter_struct( c->signature[c->index + 1 + l] != SD_BUS_TYPE_STRUCT_END) return -ENXIO; - r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets); + r = message_peek_body(m, &m->rindex, 8, 0, NULL); if (r < 0) return r; @@ -4034,10 +2967,7 @@ static int bus_message_enter_struct( static int bus_message_enter_dict_entry( sd_bus_message *m, struct bus_container *c, - const char *contents, - size_t *item_size, - size_t **offsets, - size_t *n_offsets) { + const char *contents) { size_t l; int r; @@ -4062,7 +2992,7 @@ static int bus_message_enter_dict_entry( c->signature[c->index + 1 + l] != SD_BUS_TYPE_DICT_ENTRY_END) return -ENXIO; - r = enter_struct_or_dict_entry(m, c, contents, item_size, offsets, n_offsets); + r = message_peek_body(m, &m->rindex, 8, 0, NULL); if (r < 0) return r; @@ -4078,9 +3008,7 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m, struct bus_container *c; uint32_t *array_size = NULL; _cleanup_free_ char *signature = NULL; - size_t before, end; - _cleanup_free_ size_t *offsets = NULL; - size_t n_offsets = 0, item_size = 0; + size_t before; int r; assert_return(m, -EINVAL); @@ -4144,26 +3072,19 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m, before = m->rindex; if (type == SD_BUS_TYPE_ARRAY) - r = bus_message_enter_array(m, c, contents, &array_size, &item_size, &offsets, &n_offsets); + r = bus_message_enter_array(m, c, contents, &array_size); else if (type == SD_BUS_TYPE_VARIANT) - r = bus_message_enter_variant(m, c, contents, &item_size); + r = bus_message_enter_variant(m, c, contents); else if (type == SD_BUS_TYPE_STRUCT) - r = bus_message_enter_struct(m, c, contents, &item_size, &offsets, &n_offsets); + r = bus_message_enter_struct(m, c, contents); else if (type == SD_BUS_TYPE_DICT_ENTRY) - r = bus_message_enter_dict_entry(m, c, contents, &item_size, &offsets, &n_offsets); + r = bus_message_enter_dict_entry(m, c, contents); else r = -EINVAL; if (r <= 0) return r; /* OK, let's fill it in */ - if (BUS_MESSAGE_IS_GVARIANT(m) && - type == SD_BUS_TYPE_STRUCT && - isempty(signature)) - end = m->rindex + 0; - else - end = m->rindex + c->item_size; - m->containers[m->n_containers++] = (struct bus_container) { .enclosing = type, .signature = TAKE_PTR(signature), @@ -4171,11 +3092,8 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m, .before = before, .begin = m->rindex, /* Unary type has fixed size of 1, but virtual size of 0 */ - .end = end, + .end = m->rindex, .array_size = array_size, - .item_size = item_size, - .offsets = TAKE_PTR(offsets), - .n_offsets = n_offsets, }; return 1; @@ -4183,8 +3101,6 @@ _public_ int sd_bus_message_enter_container(sd_bus_message *m, _public_ int sd_bus_message_exit_container(sd_bus_message *m) { struct bus_container *c; - unsigned saved; - int r; assert_return(m, -EINVAL); assert_return(m->sealed, -EPERM); @@ -4197,11 +3113,7 @@ _public_ int sd_bus_message_exit_container(sd_bus_message *m) { return -EBUSY; } - if (BUS_MESSAGE_IS_GVARIANT(m)) { - if (m->rindex < c->end) - return -EBUSY; - - } else if (c->enclosing == SD_BUS_TYPE_ARRAY) { + if (c->enclosing == SD_BUS_TYPE_ARRAY) { uint32_t l; l = BUS_MESSAGE_BSWAP32(m, *c->array_size); @@ -4211,14 +3123,6 @@ _public_ int sd_bus_message_exit_container(sd_bus_message *m) { message_free_last_container(m); - c = message_get_last_container(m); - saved = c->index; - c->index = c->saved_index; - r = container_next_item(m, c, &m->rindex); - c->index = saved; - if (r < 0) - return r; - return 1; } @@ -4316,65 +3220,27 @@ _public_ int sd_bus_message_peek_type(sd_bus_message *m, char *type, const char if (c->signature[c->index] == SD_BUS_TYPE_VARIANT) { if (contents) { + size_t rindex, l; void *q; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - size_t k; + rindex = m->rindex; + r = message_peek_body(m, &rindex, 1, 1, &q); + if (r < 0) + return r; - if (c->item_size < 2) - return -EBADMSG; + l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; - /* Look for the NUL delimiter that - separates the payload from the - signature. Since the body might be - in a different part that then the - signature we map byte by byte. */ + r = message_peek_body(m, &rindex, 1, l+1, &q); + if (r < 0) + return r; - for (k = 2; k <= c->item_size; k++) { - size_t where; + if (!validate_signature(q, l)) + return -EBADMSG; - where = m->rindex + c->item_size - k; - r = message_peek_body(m, &where, 1, k, &q); - if (r < 0) - return r; - - if (*(char*) q == 0) - break; - } - - if (k > c->item_size) - return -EBADMSG; - - if (free_and_strndup(&c->peeked_signature, - (char*) q + 1, k - 1) < 0) - return -ENOMEM; - - if (!signature_is_valid(c->peeked_signature, true)) - return -EBADMSG; - - *contents = c->peeked_signature; - } else { - size_t rindex, l; - - rindex = m->rindex; - r = message_peek_body(m, &rindex, 1, 1, &q); - if (r < 0) - return r; - - l = *(uint8_t*) q; - if (l == UINT8_MAX) - /* avoid overflow right below */ - return -EBADMSG; - - r = message_peek_body(m, &rindex, 1, l+1, &q); - if (r < 0) - return r; - - if (!validate_signature(q, l)) - return -EBADMSG; - - *contents = q; - } + *contents = q; } if (type) @@ -4411,9 +3277,6 @@ _public_ int sd_bus_message_rewind(sd_bus_message *m, int complete) { m->rindex = c->begin; } - c->offset_index = 0; - c->item_size = (c->n_offsets > 0 ? c->offsets[0] : c->end) - c->begin; - return !isempty(c->signature); } @@ -4818,19 +3681,11 @@ _public_ int sd_bus_message_read_array( c = message_get_last_container(m); - if (BUS_MESSAGE_IS_GVARIANT(m)) { - align = bus_gvariant_get_alignment(CHAR_TO_STR(type)); - if (align < 0) - return align; + align = bus_type_get_alignment(type); + if (align < 0) + return align; - sz = c->end - c->begin; - } else { - align = bus_type_get_alignment(type); - if (align < 0) - return align; - - sz = BUS_MESSAGE_BSWAP32(m, *c->array_size); - } + sz = BUS_MESSAGE_BSWAP32(m, *c->array_size); if (sz == 0) /* Zero length array, let's return some aligned @@ -4863,11 +3718,35 @@ static int message_peek_fields( size_t nbytes, void **ret) { + size_t start, end; + assert(m); assert(rindex); assert(align > 0); - return buffer_peek(BUS_MESSAGE_FIELDS(m), m->fields_size, rindex, align, nbytes, ret); + start = ALIGN_TO(*rindex, align); + if (start > m->fields_size) + return -EBADMSG; + + /* Avoid overflow below */ + if (nbytes > SIZE_MAX - start) + return -EBADMSG; + + end = start + nbytes; + if (end > m->fields_size) + return -EBADMSG; + + /* Verify that padding is 0 */ + uint8_t *p = BUS_MESSAGE_FIELDS(m); + for (size_t k = *rindex; k < start; k++) + if (p[k] != 0) + return -EBADMSG; + + if (ret) + *ret = p + start; + + *rindex = end; + return 1; } static int message_peek_field_uint32( @@ -4882,11 +3761,6 @@ static int message_peek_field_uint32( assert(m); assert(ri); - if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 4) - return -EBADMSG; - - /* identical for gvariant and dbus1 */ - r = message_peek_fields(m, ri, 4, 4, &q); if (r < 0) return r; @@ -4897,33 +3771,6 @@ static int message_peek_field_uint32( return 0; } -static int message_peek_field_uint64( - sd_bus_message *m, - size_t *ri, - size_t item_size, - uint64_t *ret) { - - int r; - void *q; - - assert(m); - assert(ri); - - if (BUS_MESSAGE_IS_GVARIANT(m) && item_size != 8) - return -EBADMSG; - - /* identical for gvariant and dbus1 */ - - r = message_peek_fields(m, ri, 8, 8, &q); - if (r < 0) - return r; - - if (ret) - *ret = BUS_MESSAGE_BSWAP64(m, *(uint64_t*) q); - - return 0; -} - static int message_peek_field_string( sd_bus_message *m, bool (*validate)(const char *p), @@ -4938,29 +3785,17 @@ static int message_peek_field_string( assert(m); assert(ri); - if (BUS_MESSAGE_IS_GVARIANT(m)) { + r = message_peek_field_uint32(m, ri, 4, &l); + if (r < 0) + return r; - if (item_size <= 0) - return -EBADMSG; + if (l == UINT32_MAX) + /* avoid overflow right below */ + return -EBADMSG; - r = message_peek_fields(m, ri, 1, item_size, &q); - if (r < 0) - return r; - - l = item_size - 1; - } else { - r = message_peek_field_uint32(m, ri, 4, &l); - if (r < 0) - return r; - - if (l == UINT32_MAX) - /* avoid overflow right below */ - return -EBADMSG; - - r = message_peek_fields(m, ri, 1, l+1, &q); - if (r < 0) - return r; - } + r = message_peek_fields(m, ri, 1, l+1, &q); + if (r < 0) + return r; if (validate) { if (!validate_nul(q, l)) @@ -4992,30 +3827,18 @@ static int message_peek_field_signature( assert(m); assert(ri); - if (BUS_MESSAGE_IS_GVARIANT(m)) { + r = message_peek_fields(m, ri, 1, 1, &q); + if (r < 0) + return r; - if (item_size <= 0) - return -EBADMSG; + l = *(uint8_t*) q; + if (l == UINT8_MAX) + /* avoid overflow right below */ + return -EBADMSG; - r = message_peek_fields(m, ri, 1, item_size, &q); - if (r < 0) - return r; - - l = item_size - 1; - } else { - r = message_peek_fields(m, ri, 1, 1, &q); - if (r < 0) - return r; - - l = *(uint8_t*) q; - if (l == UINT8_MAX) - /* avoid overflow right below */ - return -EBADMSG; - - r = message_peek_fields(m, ri, 1, l+1, &q); - if (r < 0) - return r; - } + r = message_peek_fields(m, ri, 1, l+1, &q); + if (r < 0) + return r; if (!validate_signature(q, l)) return -EBADMSG; @@ -5038,7 +3861,6 @@ static int message_skip_fields( assert(m); assert(ri); assert(signature); - assert(!BUS_MESSAGE_IS_GVARIANT(m)); original_index = *ri; @@ -5163,161 +3985,30 @@ static int message_skip_fields( } } -int bus_message_parse_fields(sd_bus_message *m) { - size_t ri; - int r; +static int message_parse_fields(sd_bus_message *m) { uint32_t unix_fds = 0; bool unix_fds_set = false; - void *offsets = NULL; - unsigned n_offsets = 0; - size_t sz = 0; - unsigned i = 0; + int r; assert(m); - if (BUS_MESSAGE_IS_GVARIANT(m)) { - char *p; + m->user_body_size = m->body_size; - /* Read the signature from the end of the body variant first */ - sz = bus_gvariant_determine_word_size(BUS_MESSAGE_SIZE(m), 0); - if (m->footer_accessible < 1 + sz) - return -EBADMSG; - - p = (char*) m->footer + m->footer_accessible - (1 + sz); - for (;;) { - if (p < (char*) m->footer) - return -EBADMSG; - - if (*p == 0) { - _cleanup_free_ char *k = NULL; - size_t l; - - /* We found the beginning of the signature - * string, yay! We require the body to be a - * structure, so verify it and then strip the - * opening/closing brackets. */ - - l = (char*) m->footer + m->footer_accessible - p - (1 + sz); - if (l < 2 || - p[1] != SD_BUS_TYPE_STRUCT_BEGIN || - p[1 + l - 1] != SD_BUS_TYPE_STRUCT_END) - return -EBADMSG; - - k = memdup_suffix0(p + 1 + 1, l - 2); - if (!k) - return -ENOMEM; - - if (!signature_is_valid(k, true)) - return -EBADMSG; - - free_and_replace(m->root_container.signature, k); - break; - } - - p--; - } - - /* Calculate the actual user body size, by removing - * the trailing variant signature and struct offset - * table */ - m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p); - - /* Pull out the offset table for the fields array, if any */ - if (m->fields_size > 0) { - sz = bus_gvariant_determine_word_size(m->fields_size, 0); - if (sz > 0) { - size_t framing; - void *q; - - if (m->fields_size < sz) - return -EBADMSG; - - ri = m->fields_size - sz; - r = message_peek_fields(m, &ri, 1, sz, &q); - if (r < 0) - return r; - - framing = bus_gvariant_read_word_le(q, sz); - if (framing >= m->fields_size - sz) - return -EBADMSG; - if ((m->fields_size - framing) % sz != 0) - return -EBADMSG; - - ri = framing; - r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets); - if (r < 0) - return r; - - n_offsets = (m->fields_size - framing) / sz; - } - } - } else - m->user_body_size = m->body_size; - - ri = 0; - while (ri < m->fields_size) { - _cleanup_free_ char *sig = NULL; + for (size_t ri = 0; ri < m->fields_size; ) { const char *signature; uint64_t field_type; size_t item_size = SIZE_MAX; + uint8_t *u8; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - uint64_t *u64; + r = message_peek_fields(m, &ri, 8, 1, (void**) &u8); + if (r < 0) + return r; - if (i >= n_offsets) - break; + field_type = *u8; - if (i == 0) - ri = 0; - else - ri = ALIGN_TO(bus_gvariant_read_word_le((uint8_t*) offsets + (i-1)*sz, sz), 8); - - r = message_peek_fields(m, &ri, 8, 8, (void**) &u64); - if (r < 0) - return r; - - field_type = BUS_MESSAGE_BSWAP64(m, *u64); - } else { - uint8_t *u8; - - r = message_peek_fields(m, &ri, 8, 1, (void**) &u8); - if (r < 0) - return r; - - field_type = *u8; - } - - if (BUS_MESSAGE_IS_GVARIANT(m)) { - size_t where, end; - char *b; - void *q; - - end = bus_gvariant_read_word_le((uint8_t*) offsets + i*sz, sz); - - if (end < ri) - return -EBADMSG; - - where = ri = ALIGN_TO(ri, 8); - item_size = end - ri; - r = message_peek_fields(m, &where, 1, item_size, &q); - if (r < 0) - return r; - - b = memrchr(q, 0, item_size); - if (!b) - return -EBADMSG; - - sig = memdup_suffix0(b+1, item_size - (b+1-(char*) q)); - if (!sig) - return -ENOMEM; - - signature = sig; - item_size = b - (char*) q; - } else { - r = message_peek_field_signature(m, &ri, 0, &signature); - if (r < 0) - return r; - } + r = message_peek_field_signature(m, &ri, 0, &signature); + if (r < 0) + return r; switch (field_type) { @@ -5403,9 +4094,6 @@ int bus_message_parse_fields(sd_bus_message *m) { const char *s; char *c; - if (BUS_MESSAGE_IS_GVARIANT(m)) /* only applies to dbus1 */ - return -EBADMSG; - if (m->root_container.signature) return -EBADMSG; @@ -5424,39 +4112,27 @@ int bus_message_parse_fields(sd_bus_message *m) { break; } - case BUS_MESSAGE_HEADER_REPLY_SERIAL: + case BUS_MESSAGE_HEADER_REPLY_SERIAL: { + uint32_t serial; if (m->reply_cookie != 0) return -EBADMSG; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - /* 64bit on dbus2 */ - if (!streq(signature, "t")) - return -EBADMSG; + if (!streq(signature, "u")) + return -EBADMSG; - r = message_peek_field_uint64(m, &ri, item_size, &m->reply_cookie); - if (r < 0) - return r; - } else { - /* 32bit on dbus1 */ - uint32_t serial; + r = message_peek_field_uint32(m, &ri, item_size, &serial); + if (r < 0) + return r; - if (!streq(signature, "u")) - return -EBADMSG; - - r = message_peek_field_uint32(m, &ri, item_size, &serial); - if (r < 0) - return r; - - m->reply_cookie = serial; - } + m->reply_cookie = serial; if (m->reply_cookie == 0) return -EBADMSG; break; - + } case BUS_MESSAGE_HEADER_UNIX_FDS: if (unix_fds_set) return -EBADMSG; @@ -5472,14 +4148,10 @@ int bus_message_parse_fields(sd_bus_message *m) { break; default: - if (!BUS_MESSAGE_IS_GVARIANT(m)) - r = message_skip_fields(m, &ri, UINT32_MAX, (const char **) &signature); + r = message_skip_fields(m, &ri, UINT32_MAX, (const char **) &signature); } - if (r < 0) return r; - - i++; } if (m->n_fds != unix_fds) @@ -5529,20 +4201,6 @@ int bus_message_parse_fields(sd_bus_message *m) { m->root_container.end = m->user_body_size; - if (BUS_MESSAGE_IS_GVARIANT(m)) { - r = build_struct_offsets( - m, - m->root_container.signature, - m->user_body_size, - &m->root_container.item_size, - &m->root_container.offsets, - &m->root_container.n_offsets); - if (r == -EINVAL) - return -EBADMSG; - if (r < 0) - return r; - } - /* Try to read the error message, but if we can't it's a non-issue */ if (m->header->type == SD_BUS_MESSAGE_METHOD_ERROR) (void) sd_bus_message_read(m, "s", &m->error.message); diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h index e5bf5df160b..b51fb896ed4 100644 --- a/src/libsystemd/sd-bus/bus-message.h +++ b/src/libsystemd/sd-bus/bus-message.h @@ -14,21 +14,16 @@ struct bus_container { char enclosing; - bool need_offsets:1; - /* Indexes into the signature string */ + /* Indexes into the signature string */ unsigned index, saved_index; char *signature; size_t before, begin, end; - /* dbus1: pointer to the array size value, if this is a value */ + /* pointer to the array size value, if this is a value */ uint32_t *array_size; - /* gvariant: list of offsets to end of children if this is struct/dict entry/array */ - size_t *offsets, n_offsets, offset_index; - size_t item_size; - char *peeked_signature; }; @@ -86,13 +81,8 @@ struct sd_bus_message { bool poisoned:1; bool sensitive:1; - /* The first and last bytes of the message */ + /* The first bytes of the message */ struct bus_header *header; - void *footer; - - /* How many bytes are accessible in the above pointers */ - size_t header_accessible; - size_t footer_accessible; size_t fields_size; size_t body_size; @@ -148,10 +138,7 @@ static inline uint64_t BUS_MESSAGE_BSWAP64(sd_bus_message *m, uint64_t u) { } static inline uint64_t BUS_MESSAGE_COOKIE(sd_bus_message *m) { - if (m->header->version == 2) - return BUS_MESSAGE_BSWAP64(m, m->header->dbus2.cookie); - - return BUS_MESSAGE_BSWAP32(m, m->header->dbus1.serial); + return BUS_MESSAGE_BSWAP32(m, m->header->serial); } static inline size_t BUS_MESSAGE_SIZE(sd_bus_message *m) { @@ -171,26 +158,9 @@ static inline void* BUS_MESSAGE_FIELDS(sd_bus_message *m) { return (uint8_t*) m->header + sizeof(struct bus_header); } -static inline bool BUS_MESSAGE_IS_GVARIANT(sd_bus_message *m) { - return m->header->version == 2; -} - int bus_message_get_blob(sd_bus_message *m, void **buffer, size_t *sz); int bus_message_read_strv_extend(sd_bus_message *m, char ***l); -int bus_message_from_header( - sd_bus *bus, - void *header, - size_t header_accessible, - void *footer, - size_t footer_accessible, - size_t message_size, - int *fds, - size_t n_fds, - const char *label, - size_t extra, - sd_bus_message **ret); - int bus_message_from_malloc( sd_bus *bus, void *buffer, @@ -203,18 +173,12 @@ int bus_message_from_malloc( int bus_message_get_arg(sd_bus_message *m, unsigned i, const char **str); int bus_message_get_arg_strv(sd_bus_message *m, unsigned i, char ***strv); -int bus_message_parse_fields(sd_bus_message *m); - -struct bus_body_part *message_append_part(sd_bus_message *m); - #define MESSAGE_FOREACH_PART(part, i, m) \ for ((i) = 0, (part) = &(m)->body; (i) < (m)->n_body_parts; (i)++, (part) = (part)->next) int bus_body_part_map(struct bus_body_part *part); void bus_body_part_unmap(struct bus_body_part *part); -int bus_message_to_errno(sd_bus_message *m); - int bus_message_new_synthetic_error(sd_bus *bus, uint64_t serial, const sd_bus_error *e, sd_bus_message **m); int bus_message_remarshal(sd_bus *bus, sd_bus_message **m); diff --git a/src/libsystemd/sd-bus/bus-protocol.h b/src/libsystemd/sd-bus/bus-protocol.h index c41ab58faa8..be46b5f6a73 100644 --- a/src/libsystemd/sd-bus/bus-protocol.h +++ b/src/libsystemd/sd-bus/bus-protocol.h @@ -8,32 +8,15 @@ /* Packet header */ struct _packed_ bus_header { - /* The first four fields are identical for dbus1, and dbus2 */ uint8_t endian; uint8_t type; uint8_t flags; uint8_t version; - - union _packed_ { - /* dbus1: Used for SOCK_STREAM connections */ - struct _packed_ { - uint32_t body_size; - - /* Note that what the bus spec calls "serial" we'll call - "cookie" instead, because we don't want to imply that the - cookie was in any way monotonically increasing. */ - uint32_t serial; - uint32_t fields_size; - } dbus1; - - /* dbus2: Used for kdbus connections */ - struct _packed_ { - uint32_t _reserved; - uint64_t cookie; - } dbus2; - - /* Note that both header versions have the same size! */ - }; + uint32_t body_size; + /* Note that what the bus spec calls "serial" we'll call "cookie" instead, because we don't + * want to imply that the cookie was in any way monotonically increasing. */ + uint32_t serial; + uint32_t fields_size; }; /* Endianness */ diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c index 14951ccb330..bf70e19826f 100644 --- a/src/libsystemd/sd-bus/bus-socket.c +++ b/src/libsystemd/sd-bus/bus-socket.c @@ -1124,7 +1124,7 @@ static int bus_socket_read_message_need(sd_bus *bus, size_t *need) { } else return -EBADMSG; - sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a; + sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN8(b) + (uint64_t) a; if (sum >= BUS_MESSAGE_SIZE_MAX) return -ENOBUFS; diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index c7a58e95cc4..9db6a6a194f 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1966,10 +1966,8 @@ int bus_seal_synthetic_message(sd_bus *b, sd_bus_message *m) { * hence let's fill something in for synthetic messages. Since * synthetic messages might have a fake sender and we don't * want to interfere with the real sender's serial numbers we - * pick a fixed, artificial one. We use UINT32_MAX rather - * than UINT64_MAX since dbus1 only had 32bit identifiers, - * even though kdbus can do 64bit. */ - return sd_bus_message_seal(m, 0xFFFFFFFFULL, 0); + * pick a fixed, artificial one. */ + return sd_bus_message_seal(m, UINT32_MAX, 0); } static int bus_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) { diff --git a/src/libsystemd/sd-bus/test-bus-error.c b/src/libsystemd/sd-bus/test-bus-error.c index 952455255dc..cc59de12b4d 100644 --- a/src/libsystemd/sd-bus/test-bus-error.c +++ b/src/libsystemd/sd-bus/test-bus-error.c @@ -131,11 +131,11 @@ static int dump_mapping_table(void) { const sd_bus_error_map *m; printf("----- errno mappings ------\n"); - m = ALIGN_TO_PTR(__start_SYSTEMD_BUS_ERROR_MAP, sizeof(void*)); + m = ALIGN_PTR(__start_SYSTEMD_BUS_ERROR_MAP); while (m < __stop_SYSTEMD_BUS_ERROR_MAP) { if (m->code == BUS_ERROR_MAP_END_MARKER) { - m = ALIGN_TO_PTR(m + 1, sizeof(void*)); + m = ALIGN_PTR(m + 1); continue; } diff --git a/src/libsystemd/sd-bus/test-bus-gvariant.c b/src/libsystemd/sd-bus/test-bus-gvariant.c deleted file mode 100644 index 47b1752360c..00000000000 --- a/src/libsystemd/sd-bus/test-bus-gvariant.c +++ /dev/null @@ -1,206 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#if HAVE_GLIB -#include -#endif - -#include "sd-bus.h" - -#include "alloc-util.h" -#include "bus-dump.h" -#include "bus-gvariant.h" -#include "bus-internal.h" -#include "bus-message.h" -#include "macro.h" -#include "tests.h" -#include "util.h" - -TEST(bus_gvariant_is_fixed_size) { - assert_se(bus_gvariant_is_fixed_size("") > 0); - assert_se(bus_gvariant_is_fixed_size("()") == -EINVAL); - assert_se(bus_gvariant_is_fixed_size("y") > 0); - assert_se(bus_gvariant_is_fixed_size("u") > 0); - assert_se(bus_gvariant_is_fixed_size("b") > 0); - assert_se(bus_gvariant_is_fixed_size("n") > 0); - assert_se(bus_gvariant_is_fixed_size("q") > 0); - assert_se(bus_gvariant_is_fixed_size("i") > 0); - assert_se(bus_gvariant_is_fixed_size("t") > 0); - assert_se(bus_gvariant_is_fixed_size("d") > 0); - assert_se(bus_gvariant_is_fixed_size("s") == 0); - assert_se(bus_gvariant_is_fixed_size("o") == 0); - assert_se(bus_gvariant_is_fixed_size("g") == 0); - assert_se(bus_gvariant_is_fixed_size("h") > 0); - assert_se(bus_gvariant_is_fixed_size("ay") == 0); - assert_se(bus_gvariant_is_fixed_size("v") == 0); - assert_se(bus_gvariant_is_fixed_size("(u)") > 0); - assert_se(bus_gvariant_is_fixed_size("(uuuuy)") > 0); - assert_se(bus_gvariant_is_fixed_size("(uusuuy)") == 0); - assert_se(bus_gvariant_is_fixed_size("a{ss}") == 0); - assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiii)))") > 0); - assert_se(bus_gvariant_is_fixed_size("((u)yyy(b(iiivi)))") == 0); -} - -TEST(bus_gvariant_get_size) { - assert_se(bus_gvariant_get_size("") == 0); - assert_se(bus_gvariant_get_size("()") == -EINVAL); - assert_se(bus_gvariant_get_size("y") == 1); - assert_se(bus_gvariant_get_size("u") == 4); - assert_se(bus_gvariant_get_size("b") == 1); - assert_se(bus_gvariant_get_size("n") == 2); - assert_se(bus_gvariant_get_size("q") == 2); - assert_se(bus_gvariant_get_size("i") == 4); - assert_se(bus_gvariant_get_size("t") == 8); - assert_se(bus_gvariant_get_size("d") == 8); - assert_se(bus_gvariant_get_size("s") < 0); - assert_se(bus_gvariant_get_size("o") < 0); - assert_se(bus_gvariant_get_size("g") < 0); - assert_se(bus_gvariant_get_size("h") == 4); - assert_se(bus_gvariant_get_size("ay") < 0); - assert_se(bus_gvariant_get_size("v") < 0); - assert_se(bus_gvariant_get_size("(u)") == 4); - assert_se(bus_gvariant_get_size("(uuuuy)") == 20); - assert_se(bus_gvariant_get_size("(uusuuy)") < 0); - assert_se(bus_gvariant_get_size("a{ss}") < 0); - assert_se(bus_gvariant_get_size("((u)yyy(b(iiii)))") == 28); - assert_se(bus_gvariant_get_size("((u)yyy(b(iiivi)))") < 0); - assert_se(bus_gvariant_get_size("((b)(t))") == 16); - assert_se(bus_gvariant_get_size("((b)(b)(t))") == 16); - assert_se(bus_gvariant_get_size("(bt)") == 16); - assert_se(bus_gvariant_get_size("((t)(b))") == 16); - assert_se(bus_gvariant_get_size("(tb)") == 16); - assert_se(bus_gvariant_get_size("((b)(b))") == 2); - assert_se(bus_gvariant_get_size("((t)(t))") == 16); -} - -TEST(bus_gvariant_get_alignment) { - assert_se(bus_gvariant_get_alignment("") == 1); - assert_se(bus_gvariant_get_alignment("()") == -EINVAL); - assert_se(bus_gvariant_get_alignment("y") == 1); - assert_se(bus_gvariant_get_alignment("b") == 1); - assert_se(bus_gvariant_get_alignment("u") == 4); - assert_se(bus_gvariant_get_alignment("s") == 1); - assert_se(bus_gvariant_get_alignment("o") == 1); - assert_se(bus_gvariant_get_alignment("g") == 1); - assert_se(bus_gvariant_get_alignment("v") == 8); - assert_se(bus_gvariant_get_alignment("h") == 4); - assert_se(bus_gvariant_get_alignment("i") == 4); - assert_se(bus_gvariant_get_alignment("t") == 8); - assert_se(bus_gvariant_get_alignment("x") == 8); - assert_se(bus_gvariant_get_alignment("q") == 2); - assert_se(bus_gvariant_get_alignment("n") == 2); - assert_se(bus_gvariant_get_alignment("d") == 8); - assert_se(bus_gvariant_get_alignment("ay") == 1); - assert_se(bus_gvariant_get_alignment("as") == 1); - assert_se(bus_gvariant_get_alignment("au") == 4); - assert_se(bus_gvariant_get_alignment("an") == 2); - assert_se(bus_gvariant_get_alignment("ans") == 2); - assert_se(bus_gvariant_get_alignment("ant") == 8); - assert_se(bus_gvariant_get_alignment("(ss)") == 1); - assert_se(bus_gvariant_get_alignment("(ssu)") == 4); - assert_se(bus_gvariant_get_alignment("a(ssu)") == 4); - assert_se(bus_gvariant_get_alignment("(u)") == 4); - assert_se(bus_gvariant_get_alignment("(uuuuy)") == 4); - assert_se(bus_gvariant_get_alignment("(uusuuy)") == 4); - assert_se(bus_gvariant_get_alignment("a{ss}") == 1); - assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiii)))") == 4); - assert_se(bus_gvariant_get_alignment("((u)yyy(b(iiivi)))") == 8); - assert_se(bus_gvariant_get_alignment("((b)(t))") == 8); - assert_se(bus_gvariant_get_alignment("((b)(b)(t))") == 8); - assert_se(bus_gvariant_get_alignment("(bt)") == 8); - assert_se(bus_gvariant_get_alignment("((t)(b))") == 8); - assert_se(bus_gvariant_get_alignment("(tb)") == 8); - assert_se(bus_gvariant_get_alignment("((b)(b))") == 1); - assert_se(bus_gvariant_get_alignment("((t)(t))") == 8); -} - -TEST_RET(marshal) { - _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *n = NULL; - _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; - _cleanup_free_ void *blob = NULL; - size_t sz; - int r; - - r = sd_bus_open_user(&bus); - if (r < 0) - r = sd_bus_open_system(&bus); - if (r < 0) - return log_tests_skipped_errno(r, "Failed to connect to bus"); - - bus->message_version = 2; /* dirty hack to enable gvariant */ - - r = sd_bus_message_new_method_call(bus, &m, "a.service.name", - "/an/object/path/which/is/really/really/long/so/that/we/hit/the/eight/bit/boundary/by/quite/some/margin/to/test/this/stuff/that/it/really/works", - "an.interface.name", "AMethodName"); - assert_se(r >= 0); - - assert_cc(sizeof(struct bus_header) == 16); - - assert_se(sd_bus_message_append(m, - "a(usv)", 3, - 4711, "first-string-parameter", "(st)", "X", (uint64_t) 1111, - 4712, "second-string-parameter", "(a(si))", 2, "Y", 5, "Z", 6, - 4713, "third-string-parameter", "(uu)", 1, 2) >= 0); - - assert_se(sd_bus_message_seal(m, 4711, 0) >= 0); - -#if HAVE_GLIB - { - GVariant *v; - char *t; - -#if !defined(GLIB_VERSION_2_36) - g_type_init(); -#endif - - v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv})"), m->header, sizeof(struct bus_header) + m->fields_size, false, NULL, NULL); - assert_se(g_variant_is_normal_form(v)); - t = g_variant_print(v, TRUE); - printf("%s\n", t); - g_free(t); - g_variant_unref(v); - - v = g_variant_new_from_data(G_VARIANT_TYPE("(a(usv))"), m->body.data, m->user_body_size, false, NULL, NULL); - assert_se(g_variant_is_normal_form(v)); - t = g_variant_print(v, TRUE); - printf("%s\n", t); - g_free(t); - g_variant_unref(v); - } -#endif - - assert_se(sd_bus_message_dump(m, NULL, SD_BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); - - assert_se(bus_message_get_blob(m, &blob, &sz) >= 0); - -#if HAVE_GLIB - { - GVariant *v; - char *t; - - v = g_variant_new_from_data(G_VARIANT_TYPE("(yyyyuta{tv}v)"), blob, sz, false, NULL, NULL); - assert_se(g_variant_is_normal_form(v)); - t = g_variant_print(v, TRUE); - printf("%s\n", t); - g_free(t); - g_variant_unref(v); - } -#endif - - assert_se(bus_message_from_malloc(bus, blob, sz, NULL, 0, NULL, &n) >= 0); - blob = NULL; - - assert_se(sd_bus_message_dump(n, NULL, SD_BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); - - m = sd_bus_message_unref(m); - - assert_se(sd_bus_message_new_method_call(bus, &m, "a.x", "/a/x", "a.x", "Ax") >= 0); - - assert_se(sd_bus_message_append(m, "as", 0) >= 0); - - assert_se(sd_bus_message_seal(m, 4712, 0) >= 0); - assert_se(sd_bus_message_dump(m, NULL, SD_BUS_MESSAGE_DUMP_WITH_HEADER) >= 0); - - return EXIT_SUCCESS; -} - -DEFINE_TEST_MAIN(LOG_DEBUG); diff --git a/src/shared/tests.h b/src/shared/tests.h index ade527590bc..a2f7f38c41e 100644 --- a/src/shared/tests.h +++ b/src/shared/tests.h @@ -88,7 +88,7 @@ static inline int run_test_table(void) { if (!__start_SYSTEMD_TEST_TABLE) return r; - const TestFunc *t = ALIGN_TO_PTR(__start_SYSTEMD_TEST_TABLE, sizeof(TestFunc*)); + const TestFunc *t = ALIGN_PTR(__start_SYSTEMD_TEST_TABLE); while (t < __stop_SYSTEMD_TEST_TABLE) { if (t->sd_booted && sd_booted() <= 0) { @@ -106,7 +106,7 @@ static inline int run_test_table(void) { t->f.void_func(); } - t = ALIGN_TO_PTR(t + 1, sizeof(TestFunc*)); + t = ALIGN_PTR(t + 1); } return r;