|
|
a3e2b5 |
From ed560bc85cd2537dd083a8995b5d10f66f7a391f Mon Sep 17 00:00:00 2001
|
|
|
a3e2b5 |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
a3e2b5 |
Date: Thu, 17 Jan 2019 18:31:59 +0100
|
|
|
a3e2b5 |
Subject: [PATCH] sd-bus: use "queue" message references for managing r/w
|
|
|
a3e2b5 |
message queues in connection objects
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
Let's make use of the new concept the previous commit added.
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
See: #4846
|
|
|
a3e2b5 |
(cherry picked from commit c1757a70eac0382c4837a3833d683919f6a48ed7)
|
|
|
a3e2b5 |
Related: CVE-2020-1712
|
|
|
a3e2b5 |
---
|
|
|
a3e2b5 |
src/libsystemd/sd-bus/bus-socket.c | 6 ++-
|
|
|
a3e2b5 |
src/libsystemd/sd-bus/sd-bus.c | 60 ++++++++++++++----------------
|
|
|
a3e2b5 |
2 files changed, 32 insertions(+), 34 deletions(-)
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
|
|
|
a3e2b5 |
index 17cfa8e1fd..4a72795d2b 100644
|
|
|
a3e2b5 |
--- a/src/libsystemd/sd-bus/bus-socket.c
|
|
|
a3e2b5 |
+++ b/src/libsystemd/sd-bus/bus-socket.c
|
|
|
a3e2b5 |
@@ -1116,8 +1116,10 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) {
|
|
|
a3e2b5 |
bus->fds = NULL;
|
|
|
a3e2b5 |
bus->n_fds = 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- if (t)
|
|
|
a3e2b5 |
- bus->rqueue[bus->rqueue_size++] = t;
|
|
|
a3e2b5 |
+ if (t) {
|
|
|
a3e2b5 |
+ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus);
|
|
|
a3e2b5 |
+ sd_bus_message_unref(t);
|
|
|
a3e2b5 |
+ }
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
return 1;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
|
|
a3e2b5 |
index 68ad6cbe89..a3509f7e89 100644
|
|
|
a3e2b5 |
--- a/src/libsystemd/sd-bus/sd-bus.c
|
|
|
a3e2b5 |
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
|
|
a3e2b5 |
@@ -148,13 +148,13 @@ static void bus_reset_queues(sd_bus *b) {
|
|
|
a3e2b5 |
assert(b);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
while (b->rqueue_size > 0)
|
|
|
a3e2b5 |
- sd_bus_message_unref(b->rqueue[--b->rqueue_size]);
|
|
|
a3e2b5 |
+ bus_message_unref_queued(b->rqueue[--b->rqueue_size], b);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
b->rqueue = mfree(b->rqueue);
|
|
|
a3e2b5 |
b->rqueue_allocated = 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
while (b->wqueue_size > 0)
|
|
|
a3e2b5 |
- sd_bus_message_unref(b->wqueue[--b->wqueue_size]);
|
|
|
a3e2b5 |
+ bus_message_unref_queued(b->wqueue[--b->wqueue_size], b);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
b->wqueue = mfree(b->wqueue);
|
|
|
a3e2b5 |
b->wqueue_allocated = 0;
|
|
|
a3e2b5 |
@@ -493,7 +493,7 @@ static int synthesize_connected_signal(sd_bus *bus) {
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
/* Insert at the very front */
|
|
|
a3e2b5 |
memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size);
|
|
|
a3e2b5 |
- bus->rqueue[0] = TAKE_PTR(m);
|
|
|
a3e2b5 |
+ bus->rqueue[0] = bus_message_ref_queued(m, bus);
|
|
|
a3e2b5 |
bus->rqueue_size++;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
return 0;
|
|
|
a3e2b5 |
@@ -1760,7 +1760,7 @@ static int dispatch_wqueue(sd_bus *bus) {
|
|
|
a3e2b5 |
* anyway. */
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
bus->wqueue_size--;
|
|
|
a3e2b5 |
- sd_bus_message_unref(bus->wqueue[0]);
|
|
|
a3e2b5 |
+ bus_message_unref_queued(bus->wqueue[0], bus);
|
|
|
a3e2b5 |
memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
|
|
|
a3e2b5 |
bus->windex = 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
@@ -1789,6 +1789,15 @@ int bus_rqueue_make_room(sd_bus *bus) {
|
|
|
a3e2b5 |
return 0;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
+static void rqueue_drop_one(sd_bus *bus, size_t i) {
|
|
|
a3e2b5 |
+ assert(bus);
|
|
|
a3e2b5 |
+ assert(i < bus->rqueue_size);
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
+ bus_message_unref_queued(bus->rqueue[i], bus);
|
|
|
a3e2b5 |
+ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
|
|
|
a3e2b5 |
+ bus->rqueue_size--;
|
|
|
a3e2b5 |
+}
|
|
|
a3e2b5 |
+
|
|
|
a3e2b5 |
static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) {
|
|
|
a3e2b5 |
int r, ret = 0;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
@@ -1803,10 +1812,8 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd
|
|
|
a3e2b5 |
for (;;) {
|
|
|
a3e2b5 |
if (bus->rqueue_size > 0) {
|
|
|
a3e2b5 |
/* Dispatch a queued message */
|
|
|
a3e2b5 |
-
|
|
|
a3e2b5 |
- *m = bus->rqueue[0];
|
|
|
a3e2b5 |
- bus->rqueue_size--;
|
|
|
a3e2b5 |
- memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
|
|
|
a3e2b5 |
+ *m = sd_bus_message_ref(bus->rqueue[0]);
|
|
|
a3e2b5 |
+ rqueue_drop_one(bus, 0);
|
|
|
a3e2b5 |
return 1;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
@@ -1884,7 +1891,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
|
|
|
a3e2b5 |
* of the wqueue array is always allocated so
|
|
|
a3e2b5 |
* that we always can remember how much was
|
|
|
a3e2b5 |
* written. */
|
|
|
a3e2b5 |
- bus->wqueue[0] = sd_bus_message_ref(m);
|
|
|
a3e2b5 |
+ bus->wqueue[0] = bus_message_ref_queued(m, bus);
|
|
|
a3e2b5 |
bus->wqueue_size = 1;
|
|
|
a3e2b5 |
bus->windex = idx;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
@@ -1898,7 +1905,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) {
|
|
|
a3e2b5 |
if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1))
|
|
|
a3e2b5 |
return -ENOMEM;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m);
|
|
|
a3e2b5 |
+ bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus);
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
finish:
|
|
|
a3e2b5 |
@@ -2124,37 +2131,30 @@ _public_ int sd_bus_call(
|
|
|
a3e2b5 |
usec_t left;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
while (i < bus->rqueue_size) {
|
|
|
a3e2b5 |
- sd_bus_message *incoming = NULL;
|
|
|
a3e2b5 |
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL;
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- incoming = bus->rqueue[i];
|
|
|
a3e2b5 |
+ incoming = sd_bus_message_ref(bus->rqueue[i]);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (incoming->reply_cookie == cookie) {
|
|
|
a3e2b5 |
/* Found a match! */
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
|
|
|
a3e2b5 |
- bus->rqueue_size--;
|
|
|
a3e2b5 |
+ rqueue_drop_one(bus, i);
|
|
|
a3e2b5 |
log_debug_bus_message(incoming);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
if (incoming->n_fds <= 0 || bus->accept_fd) {
|
|
|
a3e2b5 |
if (reply)
|
|
|
a3e2b5 |
- *reply = incoming;
|
|
|
a3e2b5 |
- else
|
|
|
a3e2b5 |
- sd_bus_message_unref(incoming);
|
|
|
a3e2b5 |
+ *reply = TAKE_PTR(incoming);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
return 1;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
|
|
|
a3e2b5 |
- sd_bus_message_unref(incoming);
|
|
|
a3e2b5 |
- return r;
|
|
|
a3e2b5 |
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry.");
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
|
|
|
a3e2b5 |
- r = sd_bus_error_copy(error, &incoming->error);
|
|
|
a3e2b5 |
- sd_bus_message_unref(incoming);
|
|
|
a3e2b5 |
- return r;
|
|
|
a3e2b5 |
- } else {
|
|
|
a3e2b5 |
+ } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR)
|
|
|
a3e2b5 |
+ return sd_bus_error_copy(error, &incoming->error);
|
|
|
a3e2b5 |
+ else {
|
|
|
a3e2b5 |
r = -EIO;
|
|
|
a3e2b5 |
goto fail;
|
|
|
a3e2b5 |
}
|
|
|
a3e2b5 |
@@ -2164,15 +2164,11 @@ _public_ int sd_bus_call(
|
|
|
a3e2b5 |
incoming->sender &&
|
|
|
a3e2b5 |
streq(bus->unique_name, incoming->sender)) {
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1));
|
|
|
a3e2b5 |
- bus->rqueue_size--;
|
|
|
a3e2b5 |
+ rqueue_drop_one(bus, i);
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- /* Our own message? Somebody is trying
|
|
|
a3e2b5 |
- * to send its own client a message,
|
|
|
a3e2b5 |
- * let's not dead-lock, let's fail
|
|
|
a3e2b5 |
- * immediately. */
|
|
|
a3e2b5 |
+ /* Our own message? Somebody is trying to send its own client a message,
|
|
|
a3e2b5 |
+ * let's not dead-lock, let's fail immediately. */
|
|
|
a3e2b5 |
|
|
|
a3e2b5 |
- sd_bus_message_unref(incoming);
|
|
|
a3e2b5 |
r = -ELOOP;
|
|
|
a3e2b5 |
goto fail;
|
|
|
a3e2b5 |
}
|