chiark / gitweb /
sd-bus: properly match ID changes
[elogind.git] / src / libelogind / sd-bus / bus-control.c
index 11039033588be9488c3ac7526c002ac23473097d..99115d5e492f4157ee3722bc51a4e60131d63b8a 100644 (file)
@@ -1187,6 +1187,8 @@ static int add_name_change_match(sd_bus *bus,
                  * match against added ids */
                 if (!old_owner || old_owner[0] == 0) {
                         item->type = KDBUS_ITEM_ID_ADD;
+                        if (!isempty(new_owner))
+                                item->id_change.id = new_owner_id;
 
                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
                         if (r < 0)
@@ -1197,6 +1199,8 @@ static int add_name_change_match(sd_bus *bus,
                  * match against removed ids */
                 if (!new_owner || new_owner[0] == 0) {
                         item->type = KDBUS_ITEM_ID_REMOVE;
+                        if (!isempty(old_owner))
+                                item->id_change.id = old_owner_id;
 
                         r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
                         if (r < 0)
@@ -1219,7 +1223,7 @@ int bus_add_match_internal_kernel(
         size_t sz;
         const char *sender = NULL;
         size_t sender_length = 0;
-        uint64_t src_id = KDBUS_MATCH_ID_ANY;
+        uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
         bool using_bloom = false;
         unsigned i;
         bool matches_name_change = true;
@@ -1291,10 +1295,8 @@ int bus_add_match_internal_kernel(
                         break;
 
                 case BUS_MATCH_PATH_NAMESPACE:
-                        if (!streq(c->value_str, "/")) {
-                                bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
-                                using_bloom = true;
-                        }
+                        bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
+                        using_bloom = true;
                         break;
 
                 case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
@@ -1310,11 +1312,18 @@ int bus_add_match_internal_kernel(
                 }
 
                 case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST: {
-                        char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
-
-                        xsprintf(buf, "arg%i-slash-prefix", c->type - BUS_MATCH_ARG_PATH);
-                        bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
-                        using_bloom = true;
+                        /*
+                         * XXX: DBus spec defines arg[0..63]path= matching to be
+                         * a two-way glob. That is, if either string is a prefix
+                         * of the other, it matches.
+                         * This is really hard to realize in bloom-filters, as
+                         * we would have to create a bloom-match for each prefix
+                         * of @c->value_str. This is excessive, hence we just
+                         * ignore all those matches and accept everything from
+                         * the kernel. People should really avoid those matches.
+                         * If they're used in real-life some day, we will have
+                         * to properly support multiple-matches here.
+                         */
                         break;
                 }
 
@@ -1327,13 +1336,25 @@ int bus_add_match_internal_kernel(
                         break;
                 }
 
-                case BUS_MATCH_DESTINATION:
-                        /* The bloom filter does not include
-                           the destination, since it is only
-                           available for broadcast messages
-                           which do not carry a destination
-                           since they are undirected. */
+                case BUS_MATCH_DESTINATION: {
+                        /*
+                         * Kernel only supports matching on destination IDs, but
+                         * not on destination names. So just skip the
+                         * destination name restriction and verify it in
+                         * user-space on retrieval.
+                         */
+                        r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
+                        if (r < 0)
+                                return r;
+                        else if (r > 0)
+                                sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
+
+                        /* if not a broadcast, it cannot be a name-change */
+                        if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
+                                matches_name_change = false;
+
                         break;
+                }
 
                 case BUS_MATCH_ROOT:
                 case BUS_MATCH_VALUE:
@@ -1360,6 +1381,13 @@ int bus_add_match_internal_kernel(
                 item = KDBUS_ITEM_NEXT(item);
         }
 
+        if (dst_id != KDBUS_MATCH_ID_ANY) {
+                item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
+                item->type = KDBUS_ITEM_DST_ID;
+                item->id = dst_id;
+                item = KDBUS_ITEM_NEXT(item);
+        }
+
         if (using_bloom) {
                 item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
                 item->type = KDBUS_ITEM_BLOOM_MASK;