4bff0a
From 38a5ae776dc62b42ef5ced8f9812771181af528b Mon Sep 17 00:00:00 2001
4bff0a
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
4bff0a
Date: Thu, 2 Aug 2018 14:25:11 +0200
4bff0a
Subject: [PATCH] bus-message: fix calculation of offsets table
4bff0a
4bff0a
The offsets specify the ends of variable length data. We would trust the
4bff0a
incoming data, putting the offsets specified in our message
4bff0a
into the offsets tables after doing some superficial verification.
4bff0a
But when actually reading the data we apply alignment, so we would take
4bff0a
the previous offset, align it, making it bigger then current offset, and
4bff0a
then we'd try to read data of negative length.
4bff0a
4bff0a
In the attached example, the message specifies the following offsets:
4bff0a
[1, 4]
4bff0a
but the alignment of those items is
4bff0a
[1, 8]
4bff0a
so we'd calculate the second item as starting at 8 and ending at 4.
4bff0a
4bff0a
(cherry picked from commit 12603b84d2fb07603e2ea94b240c6b78ad17510e)
4bff0a
4bff0a
Resolves: #1696224
4bff0a
---
4bff0a
 src/libsystemd/sd-bus/bus-message.c           |  36 +++++++++---------
4bff0a
 ...h-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 | Bin 0 -> 28 bytes
4bff0a
 2 files changed, 18 insertions(+), 18 deletions(-)
4bff0a
 create mode 100644 test/fuzz/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5
4bff0a
4bff0a
diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c
4bff0a
index 81aaa7f59f..d0af34f632 100644
4bff0a
--- a/src/libsystemd/sd-bus/bus-message.c
4bff0a
+++ b/src/libsystemd/sd-bus/bus-message.c
4bff0a
@@ -3140,6 +3140,7 @@ static int container_next_item(sd_bus_message *m, struct bus_container *c, size_
4bff0a
                         assert(alignment > 0);
4bff0a
 
4bff0a
                         *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
4bff0a
+                        assert(c->offsets[c->offset_index+1] >= *rindex);
4bff0a
                         c->item_size = c->offsets[c->offset_index+1] - *rindex;
4bff0a
                 } else {
4bff0a
 
4bff0a
@@ -3179,6 +3180,7 @@ static int container_next_item(sd_bus_message *m, struct bus_container *c, size_
4bff0a
                 assert(alignment > 0);
4bff0a
 
4bff0a
                 *rindex = ALIGN_TO(c->offsets[c->offset_index], alignment);
4bff0a
+                assert(c->offsets[c->offset_index+1] >= *rindex);
4bff0a
                 c->item_size = c->offsets[c->offset_index+1] - *rindex;
4bff0a
 
4bff0a
                 c->offset_index++;
4bff0a
@@ -3725,7 +3727,7 @@ static int build_struct_offsets(
4bff0a
                 size_t *n_offsets) {
4bff0a
 
4bff0a
         unsigned n_variable = 0, n_total = 0, v;
4bff0a
-        size_t previous = 0, where;
4bff0a
+        size_t previous, where;
4bff0a
         const char *p;
4bff0a
         size_t sz;
4bff0a
         void *q;
4bff0a
@@ -3804,6 +3806,7 @@ static int build_struct_offsets(
4bff0a
 
4bff0a
         /* Second, loop again and build an offset table */
4bff0a
         p = signature;
4bff0a
+        previous = m->rindex;
4bff0a
         while (*p != 0) {
4bff0a
                 size_t n, offset;
4bff0a
                 int k;
4bff0a
@@ -3817,37 +3820,34 @@ static int build_struct_offsets(
4bff0a
                         memcpy(t, p, n);
4bff0a
                         t[n] = 0;
4bff0a
 
4bff0a
+                        size_t align = bus_gvariant_get_alignment(t);
4bff0a
+                        assert(align > 0);
4bff0a
+
4bff0a
+                        /* The possible start of this member after including alignment */
4bff0a
+                        size_t start = ALIGN_TO(previous, align);
4bff0a
+
4bff0a
                         k = bus_gvariant_get_size(t);
4bff0a
                         if (k < 0) {
4bff0a
                                 size_t x;
4bff0a
 
4bff0a
-                                /* variable size */
4bff0a
+                                /* Variable size */
4bff0a
                                 if (v > 0) {
4bff0a
                                         v--;
4bff0a
 
4bff0a
                                         x = bus_gvariant_read_word_le((uint8_t*) q + v*sz, sz);
4bff0a
                                         if (x >= size)
4bff0a
                                                 return -EBADMSG;
4bff0a
-                                        if (m->rindex + x < previous)
4bff0a
-                                                return -EBADMSG;
4bff0a
                                 } else
4bff0a
-                                        /* The last item's end
4bff0a
-                                         * is determined from
4bff0a
-                                         * the start of the
4bff0a
-                                         * offset array */
4bff0a
+                                        /* The last item's end is determined
4bff0a
+                                         * from the start of the offset array */
4bff0a
                                         x = size - (n_variable * sz);
4bff0a
 
4bff0a
                                 offset = m->rindex + x;
4bff0a
-
4bff0a
-                        } else {
4bff0a
-                                size_t align;
4bff0a
-
4bff0a
-                                /* fixed size */
4bff0a
-                                align = bus_gvariant_get_alignment(t);
4bff0a
-                                assert(align > 0);
4bff0a
-
4bff0a
-                                offset = (*n_offsets == 0 ? m->rindex  : ALIGN_TO((*offsets)[*n_offsets-1], align)) + k;
4bff0a
-                        }
4bff0a
+                                if (offset < start)
4bff0a
+                                        return -EBADMSG;
4bff0a
+                        } else
4bff0a
+                                /* Fixed size */
4bff0a
+                                offset = start + k;
4bff0a
                 }
4bff0a
 
4bff0a
                 previous = (*offsets)[(*n_offsets)++] = offset;
4bff0a
diff --git a/test/fuzz/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5 b/test/fuzz/fuzz-bus-message/crash-e1b811da5ca494e494b77c6bd8e1c2f2989425c5
4bff0a
new file mode 100644
4bff0a
index 0000000000000000000000000000000000000000..9d3fa0035fd360a37833e8b58cc4aea90df9de83
4bff0a
GIT binary patch
4bff0a
literal 28
4bff0a
fcmd1#|DTDG0Z1?a!8`>PAeqj{pplqVrYQgbfcytC
4bff0a
4bff0a
literal 0
4bff0a
HcmV?d00001
4bff0a