|
|
4bff0a |
From 980418c331293aeb8595fcc95cbc4a9e1a485eda Mon Sep 17 00:00:00 2001
|
|
|
4bff0a |
From: Lennart Poettering <lennart@poettering.net>
|
|
|
4bff0a |
Date: Mon, 25 Feb 2019 11:02:46 +0100
|
|
|
4bff0a |
Subject: [PATCH] sd-bus: deal with cookie overruns
|
|
|
4bff0a |
|
|
|
4bff0a |
Apparently this happens IRL. Let's carefully deal with issues like this:
|
|
|
4bff0a |
when we overrun, let's not go back to zero but instead leave the highest
|
|
|
4bff0a |
cookie bit set. We use that as indication that we are in "overrun
|
|
|
4bff0a |
territory", and then are particularly careful with checking cookies,
|
|
|
4bff0a |
i.e. that they haven't been used for still outstanding replies yet. This
|
|
|
4bff0a |
should retain the quick cookie generation behaviour we used to have, but
|
|
|
4bff0a |
permits dealing with overruns.
|
|
|
4bff0a |
|
|
|
4bff0a |
Replaces: #11804
|
|
|
4bff0a |
Fixes: #11809
|
|
|
4bff0a |
(cherry picked from commit 1f82f5bb4237ed5f015daf93f818e9db95e764b8)
|
|
|
4bff0a |
|
|
|
4bff0a |
Resolves: #1694999
|
|
|
4bff0a |
---
|
|
|
4bff0a |
src/libsystemd/sd-bus/sd-bus.c | 47 +++++++++++++++++++++++++++++++++-
|
|
|
4bff0a |
1 file changed, 46 insertions(+), 1 deletion(-)
|
|
|
4bff0a |
|
|
|
4bff0a |
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
|
|
4bff0a |
index f53a98d6bf..3583e24e64 100644
|
|
|
4bff0a |
--- a/src/libsystemd/sd-bus/sd-bus.c
|
|
|
4bff0a |
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
|
|
4bff0a |
@@ -1597,6 +1597,47 @@ _public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) {
|
|
|
4bff0a |
return 0;
|
|
|
4bff0a |
}
|
|
|
4bff0a |
|
|
|
4bff0a |
+#define COOKIE_CYCLED (UINT32_C(1) << 31)
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+static uint64_t cookie_inc(uint64_t cookie) {
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ /* Stay within the 32bit range, since classic D-Bus can't deal with more */
|
|
|
4bff0a |
+ if (cookie >= UINT32_MAX)
|
|
|
4bff0a |
+ return COOKIE_CYCLED; /* Don't go back to zero, but use the highest bit for checking
|
|
|
4bff0a |
+ * whether we are looping. */
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ return cookie + 1;
|
|
|
4bff0a |
+}
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+static int next_cookie(sd_bus *b) {
|
|
|
4bff0a |
+ uint64_t new_cookie;
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ assert(b);
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ new_cookie = cookie_inc(b->cookie);
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ /* Small optimization: don't bother with checking for cookie reuse until we overran cookiespace at
|
|
|
4bff0a |
+ * least once, but then do it thorougly. */
|
|
|
4bff0a |
+ if (FLAGS_SET(new_cookie, COOKIE_CYCLED)) {
|
|
|
4bff0a |
+ uint32_t i;
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ /* Check if the cookie is currently in use. If so, pick the next one */
|
|
|
4bff0a |
+ for (i = 0; i < COOKIE_CYCLED; i++) {
|
|
|
4bff0a |
+ if (!ordered_hashmap_contains(b->reply_callbacks, &new_cookie))
|
|
|
4bff0a |
+ goto good;
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ new_cookie = cookie_inc(new_cookie);
|
|
|
4bff0a |
+ }
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ /* Can't fulfill request */
|
|
|
4bff0a |
+ return -EBUSY;
|
|
|
4bff0a |
+ }
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+good:
|
|
|
4bff0a |
+ b->cookie = new_cookie;
|
|
|
4bff0a |
+ return 0;
|
|
|
4bff0a |
+}
|
|
|
4bff0a |
+
|
|
|
4bff0a |
static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
|
|
|
4bff0a |
int r;
|
|
|
4bff0a |
|
|
|
4bff0a |
@@ -1620,7 +1661,11 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
|
|
|
4bff0a |
return r;
|
|
|
4bff0a |
}
|
|
|
4bff0a |
|
|
|
4bff0a |
- return sd_bus_message_seal(m, ++b->cookie, timeout);
|
|
|
4bff0a |
+ r = next_cookie(b);
|
|
|
4bff0a |
+ if (r < 0)
|
|
|
4bff0a |
+ return r;
|
|
|
4bff0a |
+
|
|
|
4bff0a |
+ return sd_bus_message_seal(m, b->cookie, timeout);
|
|
|
4bff0a |
}
|
|
|
4bff0a |
|
|
|
4bff0a |
static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
|