From c01b5c6470fe91f00ed16cdf5fc02c71a428d3a2e1c9b552fc53f573dd220a24 Mon Sep 17 00:00:00 2001 From: "Dr. Werner Fink" Date: Thu, 13 Mar 2014 14:17:45 +0000 Subject: [PATCH] . OBS-URL: https://build.opensuse.org/package/show/Base:System/systemd?expand=0&rev=554 --- systemd-big-endian-reply-matching.patch | 112 +++++++++++++++++------- 1 file changed, 81 insertions(+), 31 deletions(-) diff --git a/systemd-big-endian-reply-matching.patch b/systemd-big-endian-reply-matching.patch index bc456567..a9d0b971 100644 --- a/systemd-big-endian-reply-matching.patch +++ b/systemd-big-endian-reply-matching.patch @@ -1,36 +1,86 @@ -From: Olaf Kirch -Date: Date: Wed, 12 Mar 2014 13:52:50 +0000 -Subject: [PATCH] systemd big endian reply matching +--- + src/libsystemd/sd-bus/sd-bus.c | 36 +++++++++++++++++++++++++++++++----- + 1 file changed, 31 insertions(+), 5 deletions(-) -Reply matching on big endian architectures is broken in the dbus code. - -The hashmap functions, which are used to store and retrieves the reply_callback -structures of asynchronous calls, take a uint64_t pointer for the key argument. -However, the reply_cookie of the sd_bus_message is stored in a 32bit variable. - -This works nicely on x86-64, because (a) it's little endian, and (b) the struct -is padded to the next 8 byte boundary because reply_cookie is wedged between -two pointers. - -On s390x, this fails badly thanks to being big endian. - -Unfortunately, this results in complete failure of any communication -between systemd daemons and the dbus-daemon, because it never gets -past the initial Hello handshake - which is sent as an asynchronous -message. - -Signed-off-by: Olaf Kirch - -Index: systemd-210/src/libsystemd/sd-bus/bus-message.h +Index: systemd-210/src/libsystemd/sd-bus/sd-bus.c =================================================================== ---- systemd-210/src/libsystemd/sd-bus/bus-message.h -+++ systemd-210/src/libsystemd/sd-bus/bus-message.h -@@ -84,7 +84,7 @@ struct sd_bus_message { +--- systemd-210.orig/src/libsystemd/sd-bus/sd-bus.c ++++ systemd-210/src/libsystemd/sd-bus/sd-bus.c +@@ -358,6 +358,29 @@ _public_ int sd_bus_set_name(sd_bus *bus + return 0; + } - sd_bus *bus; ++/* ++ * Wrap the hashmap lookups in helper functions to ensure that the ++ * cookie pointer is always cast to 64bit before passing it to any of the ++ * hashmap functions ++ */ ++static inline int bus_add_reply_callback(sd_bus *bus, struct reply_callback *c, uint64_t cookie) ++{ ++ return hashmap_put(bus->reply_callbacks, &cookie, c); ++} ++ ++static inline struct reply_callback *bus_get_reply_callback(sd_bus *bus, uint64_t cookie) ++{ ++ return hashmap_remove(bus->reply_callbacks, &cookie); ++} ++ ++static inline void bus_drop_reply_callback(sd_bus *bus, const struct reply_callback *c) ++{ ++ struct reply_callback *cc; ++ ++ cc = bus_get_reply_callback(bus, c->cookie); ++ assert(cc == NULL || cc == c); ++} ++ + static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) { + const char *s; + int r; +@@ -1757,7 +1780,7 @@ _public_ int sd_bus_call_async( + c->cookie = BUS_MESSAGE_COOKIE(m); + c->timeout = calc_elapse(m->timeout); -- uint32_t reply_cookie; -+ uint64_t reply_cookie; +- r = hashmap_put(bus->reply_callbacks, &c->cookie, c); ++ r = bus_add_reply_callback(bus, c, c->cookie); + if (r < 0) { + free(c); + return r; +@@ -1788,7 +1811,7 @@ _public_ int sd_bus_call_async_cancel(sd + assert_return(cookie != 0, -EINVAL); + assert_return(!bus_pid_changed(bus), -ECHILD); - const char *path; - const char *interface; +- c = hashmap_remove(bus->reply_callbacks, &cookie); ++ c = bus_get_reply_callback(bus, cookie); + if (!c) + return 0; + +@@ -2062,7 +2085,7 @@ static int process_timeout(sd_bus *bus) + return r; + + assert_se(prioq_pop(bus->reply_callbacks_prioq) == c); +- hashmap_remove(bus->reply_callbacks, &c->cookie); ++ bus_drop_reply_callback(bus, c->cookie); + + bus->current = m; + bus->iteration_counter ++; +@@ -2110,7 +2133,9 @@ static int process_reply(sd_bus *bus, sd + m->header->type != SD_BUS_MESSAGE_METHOD_ERROR) + return 0; + +- c = hashmap_remove(bus->reply_callbacks, &m->reply_cookie); ++ /* caveat emptor: reply_cookie is 32bit, but the hashmap lookup uses a 64bit ++ * cookie pointer - without type checking, */ ++ c = bus_get_reply_callback(bus, m->reply_cookie); + if (!c) + return 0; + +@@ -2370,7 +2395,8 @@ static int process_closing(sd_bus *bus, + if (c->timeout != 0) + prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx); + +- hashmap_remove(bus->reply_callbacks, &c->cookie); ++ /* Remove callback from reply_callbacks hashmap */ ++ bus_drop_reply_callback(bus, c->cookie); + + bus->current = m; + bus->iteration_counter++;