diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2015-07-29 15:58:25 +0200 |
---|---|---|
committer | Lukasz Skalski <l.skalski@samsung.com> | 2015-08-26 18:24:44 +0200 |
commit | 93f3f5671a586842083fc352604419ca148c9874 (patch) | |
tree | 6675f05a0f9415daf3dfb9b49d5afd85a4cda064 | |
parent | adf63c5556069e1d836fc395edce9e253ec9d0e5 (diff) | |
download | systemd-93f3f5671a586842083fc352604419ca148c9874.tar.gz systemd-93f3f5671a586842083fc352604419ca148c9874.tar.bz2 systemd-93f3f5671a586842083fc352604419ca148c9874.zip |
sd-bus: fix encoding/decoding gvariant root container
The gvariant root container contains a 'variant' at the end, which embeds
the whole message body. This variant *must* contain a structure so we are
compatible to dbus1. Otherwise, it could encode at most 1 type, instead
of a full signature.
Our gvariant message parser already parses the variant-content as a
structure, so we're mostly good. However, it does *not* include the
opening and closing parantheses, nor does it parse them.
This patch fixes the decoder to verify a message contains the
parantheses, and also make the encoder add those parantheses into the
marshaled message.
Change-Id: I351f482f7c8fd050cbbbe64dbc9028909172c305
-rw-r--r-- | src/libsystemd/sd-bus/bus-message.c | 26 |
1 files changed, 19 insertions, 7 deletions
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index bd7539e243..06bbf77974 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -2924,18 +2924,20 @@ static int bus_message_close_header(sd_bus_message *m) { 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, 1); - d = message_extend_body(m, 1, 1 + l + sz, false, true); + 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; - memcpy((uint8_t*) d + 1, signature, l); + *((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, sz, sizeof(struct bus_header) + m->fields_size); + 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 + sz; + m->footer_accessible = 1 + l + 2 + sz; } else { m->header->dbus1.fields_size = m->fields_size; m->header->dbus1.body_size = m->body_size; @@ -5199,11 +5201,21 @@ int bus_message_parse_fields(sd_bus_message *m) { return -EBADMSG; if (*p == 0) { + size_t l; char *c; - /* We found the beginning of the signature string, yay! */ + /* 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. */ - c = strndup(p + 1, ((char*) m->footer + m->footer_accessible) - p - (1 + sz)); + 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; + + c = strndup(p + 1 + 1, l - 2); if (!c) return -ENOMEM; |