From 022fb8558e797483709ab3e9fe846f04f7026dac Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 22 Oct 2014 14:41:53 +0200 Subject: [PATCH 1/1] sd-bus: add sd_bus_message.verify_destination_id and .destination_ptr kdbus learned to accept both a numerical destination ID as well as a well-known-name. In that case, kdbus makes sure that the numerical ID is in fact the owner of the provided name and fails otherwise. This allows for race-free assertion of a bus name owner while sending a message, which is a requirement for bus-proxyd. Add two new fields to sd_bus_message, and set the numerical ID to verify_destination_id if bus_message_setup_kmsg() is called for a message with a well-known name. Also, set the destination's name in the kdbus item to .destination_ptr if it is non-NULL. Normal users should not touch these fields, and they're not publicy accessible. --- src/libsystemd/sd-bus/bus-kernel.c | 27 +++++++++++++++++++-------- src/libsystemd/sd-bus/bus-message.c | 5 +++++ src/libsystemd/sd-bus/bus-message.h | 2 ++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/libsystemd/sd-bus/bus-kernel.c b/src/libsystemd/sd-bus/bus-kernel.c index 153abee56..5e7bc1223 100644 --- a/src/libsystemd/sd-bus/bus-kernel.c +++ b/src/libsystemd/sd-bus/bus-kernel.c @@ -204,6 +204,7 @@ static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { struct bus_body_part *part; struct kdbus_item *d; + const char *destination; bool well_known; uint64_t unique; size_t sz, dl; @@ -219,8 +220,10 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { if (m->kdbus) return 0; - if (m->destination) { - r = bus_kernel_parse_unique_name(m->destination, &unique); + destination = m->destination ?: m->destination_ptr; + + if (destination) { + r = bus_kernel_parse_unique_name(destination, &unique); if (r < 0) return r; @@ -244,7 +247,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { /* Add in well-known destination header */ if (well_known) { - dl = strlen(m->destination); + dl = strlen(destination); sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1); } @@ -264,9 +267,17 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { m->kdbus->flags = ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_FLAGS_EXPECT_REPLY) | ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_FLAGS_NO_AUTO_START : 0); - m->kdbus->dst_id = - well_known ? 0 : - m->destination ? unique : KDBUS_DST_ID_BROADCAST; + + if (well_known) { + /* verify_destination_id will usually be 0, which makes the kernel driver only look + * at the provided well-known name. Otherwise, the kernel will make sure the provided + * destination id matches the owner of the provided weel-known-name, and fail if they + * differ. Currently, this is only needed for bus-proxyd. */ + m->kdbus->dst_id = m->verify_destination_id; + } else { + m->kdbus->dst_id = destination ? unique : KDBUS_DST_ID_BROADCAST; + } + m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS; m->kdbus->cookie = (uint64_t) m->header->serial; m->kdbus->priority = m->priority; @@ -284,7 +295,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { d = m->kdbus->items; if (well_known) - append_destination(&d, m->destination, dl); + append_destination(&d, destination, dl); append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m)); @@ -299,7 +310,7 @@ static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) { continue; } - if (part->memfd >= 0 && part->sealed && m->destination) { + if (part->memfd >= 0 && part->sealed && destination) { /* Try to send a memfd, if the part is * sealed and this is not a broadcast. Since we can only */ diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c index be36d9f41..1a8c445f0 100644 --- a/src/libsystemd/sd-bus/bus-message.c +++ b/src/libsystemd/sd-bus/bus-message.c @@ -148,6 +148,11 @@ static void message_free(sd_bus_message *m) { if (m->iovec != m->iovec_fixed) free(m->iovec); + if (m->destination_ptr) { + free(m->destination_ptr); + m->destination_ptr = NULL; + } + message_reset_containers(m); free(m->root_container.signature); free(m->root_container.offsets); diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h index df792945b..8aa71fa1d 100644 --- a/src/libsystemd/sd-bus/bus-message.h +++ b/src/libsystemd/sd-bus/bus-message.h @@ -100,6 +100,7 @@ struct sd_bus_message { usec_t realtime; uint64_t seqnum; int64_t priority; + uint64_t verify_destination_id; bool sealed:1; bool dont_send:1; @@ -143,6 +144,7 @@ struct sd_bus_message { char sender_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1]; char destination_buffer[3 + DECIMAL_STR_MAX(uint64_t) + 1]; + char *destination_ptr; size_t header_offsets[_BUS_MESSAGE_HEADER_MAX]; unsigned n_header_offsets; -- 2.30.2