From 42c4ebcbd4cbd7b27667eb8081ee4dc46f9ece17 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Mar 2014 20:33:22 +0100 Subject: [PATCH] sd-bus: don't look for a 64bit value when we only have 32bit value on reply cookie hash table access This broke hashtable lookups for the message cookies on s390x, which is a 64bit BE machine where accessing 32bit values as 64bit and vice versa will explode. Also, while we are at it, be a bit more careful when dealing with the 64bit cookies we expose and the 32bit serial numbers dbus uses in its payload. Problem identified by Fridrich Strba. --- src/libsystemd/sd-bus/bus-dump.c | 4 ++-- src/libsystemd/sd-bus/bus-kernel.c | 2 +- src/libsystemd/sd-bus/bus-message.c | 15 ++++++++++----- src/libsystemd/sd-bus/bus-message.h | 5 +++-- src/libsystemd/sd-bus/sd-bus.c | 12 ++++++------ 5 files changed, 22 insertions(+), 16 deletions(-) diff --git src/libsystemd/sd-bus/bus-dump.c src/libsystemd/sd-bus/bus-dump.c index 0e41549..ea81644 100644 --- src/libsystemd/sd-bus/bus-dump.c +++ src/libsystemd/sd-bus/bus-dump.c @@ -69,10 +69,10 @@ int bus_message_dump(sd_bus_message *m, FILE *f, bool with_header) { if (BUS_MESSAGE_COOKIE(m) == 0xFFFFFFFFULL) fprintf(f, " Cookie=-1"); else - fprintf(f, " Cookie=%lu", (unsigned long) BUS_MESSAGE_COOKIE(m)); + fprintf(f, " Cookie=%" PRIu64, BUS_MESSAGE_COOKIE(m)); if (m->reply_cookie != 0) - fprintf(f, " ReplyCookie=%lu", (unsigned long) m->reply_cookie); + fprintf(f, " ReplyCookie=%" PRIu64, m->reply_cookie); fputs("\n", f); diff --git src/libsystemd/sd-bus/bus-kernel.c src/libsystemd/sd-bus/bus-kernel.c index 8a2ca02..80ef15b 100644 --- src/libsystemd/sd-bus/bus-kernel.c +++ src/libsystemd/sd-bus/bus-kernel.c @@ -266,7 +266,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { well_known ? 0 : m->destination ? unique : KDBUS_DST_ID_BROADCAST; m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS; - m->kdbus->cookie = m->header->serial; + m->kdbus->cookie = (uint64_t) m->header->serial; m->kdbus->priority = m->priority; if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) diff --git src/libsystemd/sd-bus/bus-message.c src/libsystemd/sd-bus/bus-message.c index fb894ef..97ab0e3 100644 --- src/libsystemd/sd-bus/bus-message.c +++ src/libsystemd/sd-bus/bus-message.c @@ -617,7 +617,7 @@ static int message_new_reply( t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_cookie = BUS_MESSAGE_COOKIE(call); - r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie); + r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie); if (r < 0) goto fail; @@ -752,7 +752,7 @@ int bus_message_new_synthetic_error( t->header->flags |= BUS_MESSAGE_NO_REPLY_EXPECTED; t->reply_cookie = cookie; - r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, t->reply_cookie); + r = message_append_field_uint32(t, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) t->reply_cookie); if (r < 0) goto fail; @@ -5075,21 +5075,26 @@ int bus_message_parse_fields(sd_bus_message *m) { break; } - case BUS_MESSAGE_HEADER_REPLY_SERIAL: + case BUS_MESSAGE_HEADER_REPLY_SERIAL: { + uint32_t serial; + if (m->reply_cookie != 0) return -EBADMSG; if (!streq(signature, "u")) return -EBADMSG; - r = message_peek_field_uint32(m, &ri, item_size, &m->reply_cookie); + r = message_peek_field_uint32(m, &ri, item_size, &serial); if (r < 0) return r; + m->reply_cookie = serial; + if (m->reply_cookie == 0) return -EBADMSG; break; + } case BUS_MESSAGE_HEADER_UNIX_FDS: if (unix_fds != 0) @@ -5489,7 +5494,7 @@ int bus_message_remarshal(sd_bus *bus, sd_bus_message **m) { return -ENOMEM; n->reply_cookie = (*m)->reply_cookie; - r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, n->reply_cookie); + r = message_append_field_uint32(n, BUS_MESSAGE_HEADER_REPLY_SERIAL, (uint32_t) n->reply_cookie); if (r < 0) return r; diff --git src/libsystemd/sd-bus/bus-message.h src/libsystemd/sd-bus/bus-message.h index 5fbe3e6..df79294 100644 --- src/libsystemd/sd-bus/bus-message.h +++ src/libsystemd/sd-bus/bus-message.h @@ -84,7 +84,7 @@ struct sd_bus_message { sd_bus *bus; - uint32_t reply_cookie; + uint64_t reply_cookie; const char *path; const char *interface; @@ -162,7 +162,8 @@ static inline uint64_t BUS_MESSAGE_BSWAP64(sd_bus_message *m, uint64_t u) { return BUS_MESSAGE_NEED_BSWAP(m) ? bswap_64(u) : u; } -static inline uint32_t BUS_MESSAGE_COOKIE(sd_bus_message *m) { +static inline uint64_t BUS_MESSAGE_COOKIE(sd_bus_message *m) { + /* Note that we return the serial converted to a 64bit value here */ return BUS_MESSAGE_BSWAP32(m, m->header->serial); } diff --git src/libsystemd/sd-bus/sd-bus.c src/libsystemd/sd-bus/sd-bus.c index ca7c428..8e44e50 100644 --- src/libsystemd/sd-bus/sd-bus.c +++ src/libsystemd/sd-bus/sd-bus.c @@ -1486,15 +1486,15 @@ static int bus_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call return r; if (bus->is_kernel || *idx >= BUS_MESSAGE_SIZE(m)) - log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%lu reply_cookie=%lu error=%s", + log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", bus_message_type_to_string(m->header->type), strna(sd_bus_message_get_sender(m)), strna(sd_bus_message_get_destination(m)), strna(sd_bus_message_get_path(m)), strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)), - (unsigned long) BUS_MESSAGE_COOKIE(m), - (unsigned long) m->reply_cookie, + BUS_MESSAGE_COOKIE(m), + m->reply_cookie, strna(m->error.message)); return r; @@ -2253,15 +2253,15 @@ static int process_message(sd_bus *bus, sd_bus_message *m) { bus->current = m; bus->iteration_counter++; - log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%lu reply_cookie=%lu error=%s", + log_debug("Got message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error=%s", bus_message_type_to_string(m->header->type), strna(sd_bus_message_get_sender(m)), strna(sd_bus_message_get_destination(m)), strna(sd_bus_message_get_path(m)), strna(sd_bus_message_get_interface(m)), strna(sd_bus_message_get_member(m)), - (unsigned long) BUS_MESSAGE_COOKIE(m), - (unsigned long) m->reply_cookie, + BUS_MESSAGE_COOKIE(m), + m->reply_cookie, strna(m->error.message)); r = process_hello(bus, m); -- 1.7.9.2