From e0c17a7d1bdd197dfb5e24ba527bd281f404f1a9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 20 May 2020 09:05:17 +0200 Subject: [PATCH] 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. --- src/libsystemd/sd-bus/bus-message.c | 43 ++++++++++++---------- test/fuzz/fuzz-bus-message/oss-fuzz-19446 | Bin 0 -> 17 bytes 2 files changed, 24 insertions(+), 19 deletions(-) create mode 100644 test/fuzz/fuzz-bus-message/oss-fuzz-19446 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 0000000000000000000000000000000000000000..f937ef8c71ae86d9b95859b7382234ab434e761c GIT binary patch literal 17 Sc-qTRP+(Gk0tSsTO#uKG9Rh{` literal 0 Hc-jL100001 -- 2.47.3