bus: process AddMatch/RemoveMatch driver call in proxy

Previously, AddMatch/RemoveMatch calls where processed exclusively in
the proxy. That's racy however, since subscribing to a signal might not
complete before the signal is sent due to some subsequent method call.
Hence, in order to expose the same ordering guarantees as dbus1 process
the AddMatch/RemoveMatch calls from the proxy, so that they are
dispatched synchronously to all following messages, thus fixing the
race.

Ultimately, we should probabably dissolve the driver entirely into the
proxy, as it is purely a compatibility feature anyway...
This commit is contained in:
Lennart Poettering
2014-04-13 18:25:10 -07:00
parent 6e0369b0ff
commit 2a0abe5b6d
2 changed files with 61 additions and 9 deletions

View File

@@ -800,6 +800,7 @@ static int driver_unsupported(sd_bus *bus, sd_bus_message *m, void *userdata, sd
static const sd_bus_vtable driver_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("AddMatch", "s", NULL, driver_add_match, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetConnectionSELinuxSecurityContext", "s", "ay", driver_get_security_context, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetConnectionUnixProcessID", "s", "u", driver_get_pid, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetConnectionUnixUser", "s", "u", driver_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
@@ -812,7 +813,6 @@ static const sd_bus_vtable driver_vtable[] = {
SD_BUS_METHOD("NameHasOwner", "s", "b", driver_name_has_owner, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReleaseName", "s", "u", driver_release_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ReloadConfig", NULL, NULL, driver_unsupported, SD_BUS_VTABLE_DEPRECATED),
SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("RequestName", "su", "u", driver_request_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("StartServiceByName", "su", "u", driver_start_service_by_name, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_update_environment, 0),

View File

@@ -289,6 +289,47 @@ static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) {
return 1;
}
static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
int r;
assert(a);
assert(b);
assert(m);
if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
return 0;
if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
const char *match;
r = sd_bus_message_read(m, "s", &match);
if (r < 0)
return r;
r = sd_bus_add_match(a, match, NULL, NULL);
if (r < 0)
return r;
return sd_bus_reply_method_return(m, NULL);
} else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
const char *match;
r = sd_bus_message_read(m, "s", &match);
if (r < 0)
return r;
r = sd_bus_remove_match(a, match, NULL, NULL);
if (r < 0)
return r;
return sd_bus_reply_method_return(m, NULL);
} else
return 0;
return r;
}
static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
_cleanup_bus_message_unref_ sd_bus_message *n = NULL;
bool is_hello;
@@ -696,17 +737,28 @@ int main(int argc, char *argv[]) {
goto finish;
}
k = sd_bus_send(a, m, NULL);
k = process_driver(a, b, m);
if (k < 0) {
if (r == -ECONNRESET)
r = 0;
else {
r = k;
log_error("Failed to send message: %s", strerror(-r));
}
r = k;
log_error("Failed to process driver calls: %s", strerror(-r));
goto finish;
}
if (k > 0)
r = k;
else {
k = sd_bus_send(a, m, NULL);
if (k < 0) {
if (r == -ECONNRESET)
r = 0;
else {
r = k;
log_error("Failed to send message: %s", strerror(-r));
}
goto finish;
}
}
}
}