From: Zbigniew Jędrzejewski-Szmek Date: Wed, 20 May 2020 07:05:17 +0000 (+0200) Subject: bus-message: fix negative offset with ~empty message X-Git-Tag: v246-rc1~322^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e0c17a7d1bdd197dfb5e24ba527bd281f404f1a9;p=thirdparty%2Fsystemd.git bus-message: fix negative offset with ~empty message In the linked reproducer, m->fields_size == 0, and we calculate ri == -1, which of course doesn't end well. Skip the whole calculation if m->fields_size == 0, and also check that we don't go negative even if it is non-zero. Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=19446 and #15583. --- diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index 0af9cedf5a1..0b6ea996ec2 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -5202,29 +5202,34 @@ int bus_message_parse_fields(sd_bus_message *m) { * table */ m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p); - /* Pull out the offset table for the fields array */ - sz = bus_gvariant_determine_word_size(m->fields_size, 0); - if (sz > 0) { - size_t framing; - void *q; + /* 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; + 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; + 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; + 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; + n_offsets = (m->fields_size - framing) / sz; + } } } else m->user_body_size = m->body_size; diff --git a/test/fuzz/fuzz-bus-message/oss-fuzz-19446 b/test/fuzz/fuzz-bus-message/oss-fuzz-19446 new file mode 100644 index 00000000000..f937ef8c71a Binary files /dev/null and b/test/fuzz/fuzz-bus-message/oss-fuzz-19446 differ