systemd: fix CVE-2019-6454

Apply patches from systemd_237-3ubuntu10.13 to fix CVE-2019-6454.
CVE-2019-6454 is an issue in which systemd (PID1) can be crashed
with a specially formed D-Bus message.

For information see:
https://usn.ubuntu.com/3891-1/
https://git.launchpad.net/ubuntu/+source/systemd/commit/?h=applied/ubuntu/bionic-updates&id=d7584b894afcaa8a4a1abb69db2a9c81a6276e80

(From OE-Core rev: 342157b135e7493e5965b706ede93bee190fbe32)

Signed-off-by: George McCollister <george.mccollister@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
George McCollister
2019-02-25 10:37:13 -06:00
committed by Richard Purdie
parent 4c55db6d5c
commit 0278e515fd
3 changed files with 273 additions and 0 deletions

View File

@@ -0,0 +1,210 @@
Description: sd-bus: enforce a size limit for dbus paths, and don't allocate
them on the stacka
Forwarded: no
Patch from: systemd_237-3ubuntu10.13
For information see:
https://usn.ubuntu.com/3891-1/
https://git.launchpad.net/ubuntu/+source/systemd/commit/?h=applied/ubuntu/bionic-updates&id=d7584b894afcaa8a4a1abb69db2a9c81a6276e80
CVE: CVE-2019-6454
Upstream-Status: Backport
Signed-off-by: George McCollister <george.mccollister@gmail.com>
--- a/src/libsystemd/sd-bus/bus-internal.c
+++ b/src/libsystemd/sd-bus/bus-internal.c
@@ -61,7 +61,7 @@
if (slash)
return false;
- return true;
+ return (q - p) <= BUS_PATH_SIZE_MAX;
}
char* object_path_startswith(const char *a, const char *b) {
--- a/src/libsystemd/sd-bus/bus-internal.h
+++ b/src/libsystemd/sd-bus/bus-internal.h
@@ -339,6 +339,10 @@
#define BUS_MESSAGE_SIZE_MAX (64*1024*1024)
#define BUS_AUTH_SIZE_MAX (64*1024)
+/* Note that the D-Bus specification states that bus paths shall have no size limit. We enforce here one
+ * anyway, since truly unbounded strings are a security problem. The limit we pick is relatively large however,
+ * to not clash unnecessarily with real-life applications. */
+#define BUS_PATH_SIZE_MAX (64*1024)
#define BUS_CONTAINER_DEPTH 128
--- a/src/libsystemd/sd-bus/bus-objects.c
+++ b/src/libsystemd/sd-bus/bus-objects.c
@@ -1150,7 +1150,8 @@
const char *path,
sd_bus_error *error) {
- char *prefix;
+ _cleanup_free_ char *prefix = NULL;
+ size_t pl;
int r;
assert(bus);
@@ -1166,7 +1167,12 @@
return 0;
/* Second, add fallback vtables registered for any of the prefixes */
- prefix = alloca(strlen(path) + 1);
+ pl = strlen(path);
+ assert(pl <= BUS_PATH_SIZE_MAX);
+ prefix = new(char, pl + 1);
+ if (!prefix)
+ return -ENOMEM;
+
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = object_manager_serialize_path(bus, reply, prefix, path, true, error);
if (r < 0)
@@ -1362,6 +1368,7 @@
}
int bus_process_object(sd_bus *bus, sd_bus_message *m) {
+ _cleanup_free_ char *prefix = NULL;
int r;
size_t pl;
bool found_object = false;
@@ -1386,9 +1393,12 @@
assert(m->member);
pl = strlen(m->path);
- do {
- char prefix[pl+1];
+ assert(pl <= BUS_PATH_SIZE_MAX);
+ prefix = new(char, pl + 1);
+ if (!prefix)
+ return -ENOMEM;
+ do {
bus->nodes_modified = false;
r = object_find_and_run(bus, m, m->path, false, &found_object);
@@ -1516,9 +1526,15 @@
n = hashmap_get(bus->nodes, path);
if (!n) {
- char *prefix;
+ _cleanup_free_ char *prefix = NULL;
+ size_t pl;
+
+ pl = strlen(path);
+ assert(pl <= BUS_PATH_SIZE_MAX);
+ prefix = new(char, pl + 1);
+ if (!prefix)
+ return -ENOMEM;
- prefix = alloca(strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
n = hashmap_get(bus->nodes, prefix);
if (n)
@@ -2108,8 +2124,9 @@
char **names) {
BUS_DONT_DESTROY(bus);
+ _cleanup_free_ char *prefix = NULL;
bool found_interface = false;
- char *prefix;
+ size_t pl;
int r;
assert_return(bus, -EINVAL);
@@ -2128,6 +2145,12 @@
if (names && names[0] == NULL)
return 0;
+ pl = strlen(path);
+ assert(pl <= BUS_PATH_SIZE_MAX);
+ prefix = new(char, pl + 1);
+ if (!prefix)
+ return -ENOMEM;
+
do {
bus->nodes_modified = false;
@@ -2137,7 +2160,6 @@
if (bus->nodes_modified)
continue;
- prefix = alloca(strlen(path) + 1);
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = emit_properties_changed_on_interface(bus, prefix, path, interface, true, &found_interface, names);
if (r != 0)
@@ -2269,7 +2291,8 @@
static int object_added_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
_cleanup_set_free_ Set *s = NULL;
- char *prefix;
+ _cleanup_free_ char *prefix = NULL;
+ size_t pl;
int r;
assert(bus);
@@ -2314,7 +2337,12 @@
if (bus->nodes_modified)
return 0;
- prefix = alloca(strlen(path) + 1);
+ pl = strlen(path);
+ assert(pl <= BUS_PATH_SIZE_MAX);
+ prefix = new(char, pl + 1);
+ if (!prefix)
+ return -ENOMEM;
+
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = object_added_append_all_prefix(bus, m, s, prefix, path, true);
if (r < 0)
@@ -2453,7 +2481,8 @@
static int object_removed_append_all(sd_bus *bus, sd_bus_message *m, const char *path) {
_cleanup_set_free_ Set *s = NULL;
- char *prefix;
+ _cleanup_free_ char *prefix = NULL;
+ size_t pl;
int r;
assert(bus);
@@ -2485,7 +2514,12 @@
if (bus->nodes_modified)
return 0;
- prefix = alloca(strlen(path) + 1);
+ pl = strlen(path);
+ assert(pl <= BUS_PATH_SIZE_MAX);
+ prefix = new(char, pl + 1);
+ if (!prefix)
+ return -ENOMEM;
+
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = object_removed_append_all_prefix(bus, m, s, prefix, path, true);
if (r < 0)
@@ -2635,7 +2669,8 @@
const char *path,
const char *interface) {
- char *prefix;
+ _cleanup_free_ char *prefix = NULL;
+ size_t pl;
int r;
assert(bus);
@@ -2649,7 +2684,12 @@
if (bus->nodes_modified)
return 0;
- prefix = alloca(strlen(path) + 1);
+ pl = strlen(path);
+ assert(pl <= BUS_PATH_SIZE_MAX);
+ prefix = new(char, pl + 1);
+ if (!prefix)
+ return -ENOMEM;
+
OBJECT_PATH_FOREACH_PREFIX(prefix, path) {
r = interfaces_added_append_one_prefix(bus, m, prefix, path, interface, true);
if (r != 0)

View File

@@ -0,0 +1,61 @@
Description: sd-bus: if we receive an invalid dbus message, ignore and
proceeed
.
dbus-daemon might have a slightly different idea of what a valid msg is
than us (for example regarding valid msg and field sizes). Let's hence
try to proceed if we can and thus drop messages rather than fail the
connection if we fail to validate a message.
.
Hopefully the differences in what is considered valid are not visible
for real-life usecases, but are specific to exploit attempts only.
Author: Lennart Poettering <lennart@poettering.net>
Forwarded: other,https://github.com/systemd/systemd/pull/11708/
Patch from: systemd_237-3ubuntu10.13
For information see:
https://usn.ubuntu.com/3891-1/
https://git.launchpad.net/ubuntu/+source/systemd/commit/?h=applied/ubuntu/bionic-updates&id=d7584b894afcaa8a4a1abb69db2a9c81a6276e80
CVE: CVE-2019-6454
Upstream-Status: Backport
Signed-off-by: George McCollister <george.mccollister@gmail.com>
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 30d6455b6f..441b4a816f 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -1072,7 +1072,7 @@ static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
}
static int bus_socket_make_message(sd_bus *bus, size_t size) {
- sd_bus_message *t;
+ sd_bus_message *t = NULL;
void *b;
int r;
@@ -1097,7 +1097,9 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
bus->fds, bus->n_fds,
NULL,
&t);
- if (r < 0) {
+ if (r == -EBADMSG)
+ log_debug_errno(r, "Received invalid message from connection %s, dropping.", strna(bus->description));
+ else if (r < 0) {
free(b);
return r;
}
@@ -1108,7 +1110,8 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
bus->fds = NULL;
bus->n_fds = 0;
- bus->rqueue[bus->rqueue_size++] = t;
+ if (t)
+ bus->rqueue[bus->rqueue_size++] = t;
return 1;
}
--
2.17.1

View File

@@ -63,6 +63,8 @@ SRC_URI += "file://touchscreen.rules \
file://0027-journal-fix-out-of-bounds-read-CVE-2018-16866.patch \
file://0001-tmpfiles-don-t-resolve-pathnames-when-traversing-rec.patch \
file://0002-Make-tmpfiles-safe.patch \
file://CVE-2019-6454.patch \
file://sd-bus-if-we-receive-an-invalid-dbus-message-ignore-.patch \
"
SRC_URI_append_qemuall = " file://0001-core-device.c-Change-the-default-device-timeout-to-2.patch"