Blame SOURCES/0167-bus-message-fix-calculation-of-offsets-table.patch

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