mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
sd-bus: suppress installing local bus matches server side
Matches that can only match against messages from the org.freedesktop.DBus.Local service (or the local interfaces or path) should never be installed server side, suppress them hence. Similar, on kdbus matches that can only match driver messages shouldn't be passed to the kernel.
This commit is contained in:
parent
3eb3228e58
commit
cc65fe5e14
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -2952,6 +2952,16 @@ _public_ int sd_bus_add_match(
|
||||
s->match_callback.cookie = ++bus->match_cookie;
|
||||
|
||||
if (bus->bus_client) {
|
||||
enum bus_match_scope scope;
|
||||
|
||||
scope = bus_match_get_scope(components, n_components);
|
||||
|
||||
/* 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
|
||||
@ -2968,6 +2978,9 @@ _public_ int sd_bus_add_match(
|
||||
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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user