1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-14 23:24:38 +03:00

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.
This commit is contained in:
Daniel Mack 2014-10-22 14:41:53 +02:00
parent 7e27f3121e
commit 022fb8558e
3 changed files with 26 additions and 8 deletions

View File

@ -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 */

View File

@ -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);

View File

@ -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;