|
|
c62b8e |
From ac46d01c5f6a211bbbbb43e20f63ecae2549da20 Mon Sep 17 00:00:00 2001
|
|
|
e42381 |
From: Jan Synacek <jsynacek@redhat.com>
|
|
|
e42381 |
Date: Tue, 2 Apr 2019 10:23:30 +0200
|
|
|
e42381 |
Subject: [PATCH] sd-bus: deal with cookie overruns
|
|
|
e42381 |
|
|
|
e42381 |
Apparently this happens IRL. Let's carefully deal with issues like this:
|
|
|
e42381 |
when we overrun, let's not go back to zero but instead leave the highest
|
|
|
e42381 |
cookie bit set. We use that as indication that we are in "overrun
|
|
|
e42381 |
territory", and then are particularly careful with checking cookies,
|
|
|
e42381 |
i.e. that they haven't been used for still outstanding replies yet. This
|
|
|
e42381 |
should retain the quick cookie generation behaviour we used to have, but
|
|
|
e42381 |
permits dealing with overruns.
|
|
|
e42381 |
|
|
|
e42381 |
Replaces: #11804
|
|
|
e42381 |
Fixes: #11809
|
|
|
e42381 |
|
|
|
e42381 |
(cherry picked from commit 1f82f5bb4237ed5f015daf93f818e9db95e764b8)
|
|
|
c62b8e |
Resolves: #1693559
|
|
|
e42381 |
---
|
|
|
e42381 |
src/libsystemd/sd-bus/sd-bus.c | 49 +++++++++++++++++++++++++++++++++-
|
|
|
e42381 |
src/shared/macro.h | 2 ++
|
|
|
e42381 |
2 files changed, 50 insertions(+), 1 deletion(-)
|
|
|
e42381 |
|
|
|
e42381 |
diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c
|
|
|
c62b8e |
index b0a323792b..44ed2c7497 100644
|
|
|
e42381 |
--- a/src/libsystemd/sd-bus/sd-bus.c
|
|
|
e42381 |
+++ b/src/libsystemd/sd-bus/sd-bus.c
|
|
|
e42381 |
@@ -1495,7 +1495,50 @@ _public_ int sd_bus_get_bus_id(sd_bus *bus, sd_id128_t *id) {
|
|
|
e42381 |
return 0;
|
|
|
e42381 |
}
|
|
|
e42381 |
|
|
|
e42381 |
+#define COOKIE_CYCLED (UINT32_C(1) << 31)
|
|
|
e42381 |
+
|
|
|
e42381 |
+static uint64_t cookie_inc(uint64_t cookie) {
|
|
|
e42381 |
+
|
|
|
e42381 |
+ /* Stay within the 32bit range, since classic D-Bus can't deal with more */
|
|
|
e42381 |
+ if (cookie >= UINT32_MAX)
|
|
|
e42381 |
+ return COOKIE_CYCLED; /* Don't go back to zero, but use the highest bit for checking
|
|
|
e42381 |
+ * whether we are looping. */
|
|
|
e42381 |
+
|
|
|
e42381 |
+ return cookie + 1;
|
|
|
e42381 |
+}
|
|
|
e42381 |
+
|
|
|
e42381 |
+static int next_cookie(sd_bus *b) {
|
|
|
e42381 |
+ uint64_t new_cookie;
|
|
|
e42381 |
+
|
|
|
e42381 |
+ assert(b);
|
|
|
e42381 |
+
|
|
|
e42381 |
+ new_cookie = cookie_inc(b->cookie);
|
|
|
e42381 |
+
|
|
|
e42381 |
+ /* Small optimization: don't bother with checking for cookie reuse until we overran cookiespace at
|
|
|
e42381 |
+ * least once, but then do it thorougly. */
|
|
|
e42381 |
+ if (FLAGS_SET(new_cookie, COOKIE_CYCLED)) {
|
|
|
e42381 |
+ uint32_t i;
|
|
|
e42381 |
+
|
|
|
e42381 |
+ /* Check if the cookie is currently in use. If so, pick the next one */
|
|
|
e42381 |
+ for (i = 0; i < COOKIE_CYCLED; i++) {
|
|
|
e42381 |
+ if (!ordered_hashmap_contains(b->reply_callbacks, &new_cookie))
|
|
|
e42381 |
+ goto good;
|
|
|
e42381 |
+
|
|
|
e42381 |
+ new_cookie = cookie_inc(new_cookie);
|
|
|
e42381 |
+ }
|
|
|
e42381 |
+
|
|
|
e42381 |
+ /* Can't fulfill request */
|
|
|
e42381 |
+ return -EBUSY;
|
|
|
e42381 |
+ }
|
|
|
e42381 |
+
|
|
|
e42381 |
+good:
|
|
|
e42381 |
+ b->cookie = new_cookie;
|
|
|
e42381 |
+ return 0;
|
|
|
e42381 |
+}
|
|
|
e42381 |
+
|
|
|
e42381 |
static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
|
|
|
e42381 |
+ int r;
|
|
|
e42381 |
+
|
|
|
e42381 |
assert(b);
|
|
|
e42381 |
assert(m);
|
|
|
e42381 |
|
|
|
e42381 |
@@ -1510,7 +1553,11 @@ static int bus_seal_message(sd_bus *b, sd_bus_message *m, usec_t timeout) {
|
|
|
e42381 |
if (timeout == 0)
|
|
|
e42381 |
timeout = BUS_DEFAULT_TIMEOUT;
|
|
|
e42381 |
|
|
|
e42381 |
- return bus_message_seal(m, ++b->cookie, timeout);
|
|
|
e42381 |
+ r = next_cookie(b);
|
|
|
e42381 |
+ if (r < 0)
|
|
|
e42381 |
+ return r;
|
|
|
e42381 |
+
|
|
|
e42381 |
+ return bus_message_seal(m, b->cookie, timeout);
|
|
|
e42381 |
}
|
|
|
e42381 |
|
|
|
e42381 |
static int bus_remarshal_message(sd_bus *b, sd_bus_message **m) {
|
|
|
e42381 |
diff --git a/src/shared/macro.h b/src/shared/macro.h
|
|
|
c62b8e |
index 26df270d51..d4cdb1d08b 100644
|
|
|
e42381 |
--- a/src/shared/macro.h
|
|
|
e42381 |
+++ b/src/shared/macro.h
|
|
|
c62b8e |
@@ -401,6 +401,8 @@ do { \
|
|
|
e42381 |
|
|
|
e42381 |
#define SET_FLAG(v, flag, b) \
|
|
|
e42381 |
(v) = (b) ? ((v) | (flag)) : ((v) & ~(flag))
|
|
|
e42381 |
+#define FLAGS_SET(v, flags) \
|
|
|
e42381 |
+ ((~(v) & (flags)) == 0)
|
|
|
e42381 |
|
|
|
e42381 |
#define IN_SET(x, y, ...) \
|
|
|
e42381 |
({ \
|