diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dbus-common.c | 66 | ||||
-rw-r--r-- | src/dbus.c | 39 |
2 files changed, 73 insertions, 32 deletions
diff --git a/src/dbus-common.c b/src/dbus-common.c index 73f9e87eed..5bfaf361fb 100644 --- a/src/dbus-common.c +++ b/src/dbus-common.c @@ -55,7 +55,7 @@ int bus_check_peercred(DBusConnection *c) { return -E2BIG; } - if (ucred.uid != 0) + if (ucred.uid != 0 && ucred.uid != geteuid()) return -EPERM; return 1; @@ -98,27 +98,53 @@ static int sync_auth(DBusConnection *bus, DBusError *error) { return 0; } -int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private, DBusError *error) { - DBusConnection *bus; +int bus_connect(DBusBusType t, DBusConnection **_bus, bool *_private, DBusError *error) { + DBusConnection *bus = NULL; int r; + bool private = true; assert(_bus); - /* If we are root, then let's not go via the bus */ if (geteuid() == 0 && t == DBUS_BUS_SYSTEM) { + /* If we are root, then let's talk directly to the + * system instance, instead of going via the bus */ + + bus = dbus_connection_open_private("unix:path=/run/systemd/private", error); + if (!bus) + return -EIO; + + } else { + if (t == DBUS_BUS_SESSION) { + const char *e; + + /* If we are supposed to talk to the instance, + * try via XDG_RUNTIME_DIR first, then + * fallback to normal bus access */ - if (!(bus = dbus_connection_open_private("unix:path=/run/systemd/private", error))) { -#ifndef LEGACY - dbus_error_free(error); + e = getenv("XDG_RUNTIME_DIR"); + if (e) { + char *p; - /* Retry with the pre v21 socket name, to ease upgrades */ - if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", error))) -#endif + if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) + return -ENOMEM; + + bus = dbus_connection_open_private(p, NULL); + free(p); + } + } + + if (!bus) { + bus = dbus_bus_get_private(t, error); + if (!bus) return -EIO; + + private = false; } + } - dbus_connection_set_exit_on_disconnect(bus, FALSE); + dbus_connection_set_exit_on_disconnect(bus, FALSE); + if (private) { if (bus_check_peercred(bus) < 0) { dbus_connection_close(bus); dbus_connection_unref(bus); @@ -126,26 +152,18 @@ int bus_connect(DBusBusType t, DBusConnection **_bus, bool *private, DBusError * dbus_set_error_const(error, DBUS_ERROR_ACCESS_DENIED, "Failed to verify owner of bus."); return -EACCES; } - - if (private) - *private = true; - - } else { - if (!(bus = dbus_bus_get_private(t, error))) - return -EIO; - - dbus_connection_set_exit_on_disconnect(bus, FALSE); - - if (private) - *private = false; } - if ((r = sync_auth(bus, error)) < 0) { + r = sync_auth(bus, error); + if (r < 0) { dbus_connection_close(bus); dbus_connection_unref(bus); return r; } + if (_private) + *_private = private; + *_bus = bus; return 0; } diff --git a/src/dbus.c b/src/dbus.c index 8c7f0ab383..daa2c84a05 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -731,8 +731,8 @@ static int bus_setup_loop(Manager *m, DBusConnection *bus) { return 0; } -static dbus_bool_t allow_only_root(DBusConnection *connection, unsigned long uid, void *data) { - return uid == 0; +static dbus_bool_t allow_only_same_user(DBusConnection *connection, unsigned long uid, void *data) { + return uid == 0 || uid == geteuid(); } static void bus_new_connection( @@ -749,7 +749,7 @@ static void bus_new_connection( return; } - dbus_connection_set_unix_user_function(new_connection, allow_only_root, NULL, NULL); + dbus_connection_set_unix_user_function(new_connection, allow_only_same_user, NULL, NULL); if (bus_setup_loop(m, new_connection) < 0) return; @@ -930,12 +930,35 @@ static int bus_init_private(Manager *m) { if (m->private_bus) return 0; - /* We want the private bus only when running as init */ - if (getpid() != 1) - return 0; + if (m->running_as == MANAGER_SYSTEM) { + + /* We want the private bus only when running as init */ + if (getpid() != 1) + return 0; + + unlink("/run/systemd/private"); + m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error); + } else { + const char *e; + char *p; + + e = getenv("XDG_RUNTIME_DIR"); + if (!e) + return 0; + + if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) { + log_error("Not enough memory"); + r = -ENOMEM; + goto fail; + } + + mkdir_parents(p+10, 0755); + unlink(p+10); + m->private_bus = dbus_server_listen(p, &error); + free(p); + } - unlink("/run/systemd/private"); - if (!(m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error))) { + if (!m->private_bus) { log_error("Failed to create private D-Bus server: %s", bus_error_message(&error)); r = -EIO; goto fail; |