Merge pull request #244 from poettering/sdbus-suppress-local

sd-bus: suppress installing local bus matches server side
This commit is contained in:
David Herrmann 2015-06-17 12:20:03 +02:00
commit 9d8a5fd3e6
6 changed files with 88 additions and 13 deletions

View file

@ -141,6 +141,7 @@ struct sd_bus_slot {
void *userdata;
BusSlotType type:5;
bool floating:1;
bool match_added:1;
char *description;
LIST_FIELDS(sd_bus_slot, slots);

View file

@ -1149,3 +1149,40 @@ void bus_match_dump(struct bus_match_node *node, unsigned level) {
for (c = node->child; c; c = c->next)
bus_match_dump(c, level + 1);
}
enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components) {
bool found_driver = false;
unsigned i;
if (n_components <= 0)
return BUS_MATCH_GENERIC;
assert(components);
/* Checks whether the specified match can only match the
* pseudo-service for local messages, which we detect by
* sender, interface or path. If a match is not restricted to
* local messages, then we check if it only matches on the
* driver. */
for (i = 0; i < n_components; i++) {
const struct bus_match_component *c = components + i;
if (c->type == BUS_MATCH_SENDER) {
if (streq_ptr(c->value_str, "org.freedesktop.DBus.Local"))
return BUS_MATCH_LOCAL;
if (streq_ptr(c->value_str, "org.freedesktop.DBus"))
found_driver = true;
}
if (c->type == BUS_MATCH_INTERFACE && streq_ptr(c->value_str, "org.freedesktop.DBus.Local"))
return BUS_MATCH_LOCAL;
if (c->type == BUS_MATCH_PATH && streq_ptr(c->value_str, "/org/freedesktop/DBus/Local"))
return BUS_MATCH_LOCAL;
}
return found_driver ? BUS_MATCH_DRIVER : BUS_MATCH_GENERIC;
}

View file

@ -73,6 +73,12 @@ struct bus_match_component {
char *value_str;
};
enum bus_match_scope {
BUS_MATCH_GENERIC,
BUS_MATCH_LOCAL,
BUS_MATCH_DRIVER,
};
int bus_match_run(sd_bus *bus, struct bus_match_node *root, sd_bus_message *m);
int bus_match_add(struct bus_match_node *root, struct bus_match_component *components, unsigned n_components, struct match_callback *callback);
@ -90,3 +96,5 @@ enum bus_match_node_type bus_match_node_type_from_string(const char *k, size_t n
int bus_match_parse(const char *match, struct bus_match_component **_components, unsigned *_n_components);
void bus_match_parse_free(struct bus_match_component *components, unsigned n_components);
char *bus_match_to_string(struct bus_match_component *components, unsigned n_components);
enum bus_match_scope bus_match_get_scope(const struct bus_match_component *components, unsigned n_components);

View file

@ -89,7 +89,7 @@ void bus_slot_disconnect(sd_bus_slot *slot) {
case BUS_MATCH_CALLBACK:
if (slot->bus->bus_client)
if (slot->match_added)
bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
slot->bus->match_callbacks_modified = true;

View file

@ -2952,22 +2952,35 @@ _public_ int sd_bus_add_match(
s->match_callback.cookie = ++bus->match_cookie;
if (bus->bus_client) {
enum bus_match_scope scope;
if (!bus->is_kernel) {
/* When this is not a kernel transport, we
* store the original match string, so that we
* can use it to remove the match again */
scope = bus_match_get_scope(components, n_components);
s->match_callback.match_string = strdup(match);
if (!s->match_callback.match_string) {
r = -ENOMEM;
goto finish;
/* Do not install server-side matches for matches
* against the local service, interface or bus
* path. Also, when on kdbus don't install driver
* matches server side. */
if (scope == BUS_MATCH_GENERIC ||
(!bus->is_kernel && scope == BUS_MATCH_DRIVER)) {
if (!bus->is_kernel) {
/* When this is not a kernel transport, we
* store the original match string, so that we
* can use it to remove the match again */
s->match_callback.match_string = strdup(match);
if (!s->match_callback.match_string) {
r = -ENOMEM;
goto finish;
}
}
}
r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie);
if (r < 0)
goto finish;
r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie);
if (r < 0)
goto finish;
s->match_added = true;
}
}
bus->match_callbacks_modified = true;

View file

@ -77,6 +77,15 @@ static int match_add(sd_bus_slot *slots, struct bus_match_node *root, const char
return r;
}
static void test_match_scope(const char *match, enum bus_match_scope scope) {
struct bus_match_component *components = NULL;
unsigned n_components = 0;
assert_se(bus_match_parse(match, &components, &n_components) >= 0);
assert_se(bus_match_get_scope(components, n_components) == scope);
bus_match_parse_free(components, n_components);
}
int main(int argc, char *argv[]) {
struct bus_match_node root = {
.type = BUS_MATCH_ROOT,
@ -142,5 +151,12 @@ int main(int argc, char *argv[]) {
bus_match_free(&root);
test_match_scope("interface='foobar'", BUS_MATCH_GENERIC);
test_match_scope("", BUS_MATCH_GENERIC);
test_match_scope("interface='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL);
test_match_scope("sender='org.freedesktop.DBus.Local'", BUS_MATCH_LOCAL);
test_match_scope("member='gurke',path='/org/freedesktop/DBus/Local'", BUS_MATCH_LOCAL);
test_match_scope("arg2='piep',sender='org.freedesktop.DBus',member='waldo'", BUS_MATCH_DRIVER);
return 0;
}