summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mack <daniel@zonque.org>2014-10-22 14:41:53 +0200
committerDaniel Mack <daniel@zonque.org>2014-11-11 14:14:01 +0100
commit022fb8558e797483709ab3e9fe846f04f7026dac (patch)
tree506558821d73d5a71578d3bd66377be289f16d52
parent7e27f3121e5a10629302b5221eb21345f832724a (diff)
downloadsystemd-022fb8558e797483709ab3e9fe846f04f7026dac.tar.gz
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.
-rw-r--r--src/libsystemd/sd-bus/bus-kernel.c27
-rw-r--r--src/libsystemd/sd-bus/bus-message.c5
-rw-r--r--src/libsystemd/sd-bus/bus-message.h2
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 153abee56f..5e7bc12239 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 be36d9f417..1a8c445f0b 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 df792945b0..8aa71fa1d8 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;