dbus: listen on private sockets in user mode too

This commit is contained in:
Lennart Poettering 2011-07-01 22:34:37 +02:00
parent 8fef765900
commit be81bfc4a7
2 changed files with 74 additions and 33 deletions

View file

@ -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 */
if (!(bus = dbus_connection_open_private("unix:path=/run/systemd/private", error))) {
#ifndef LEGACY
dbus_error_free(error);
bus = dbus_connection_open_private("unix:path=/run/systemd/private", error);
if (!bus)
return -EIO;
/* Retry with the pre v21 socket name, to ease upgrades */
if (!(bus = dbus_connection_open_private("unix:abstract=/org/freedesktop/systemd1/private", error)))
#endif
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 */
e = getenv("XDG_RUNTIME_DIR");
if (e) {
char *p;
if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
return -ENOMEM;
bus = dbus_connection_open_private(p, NULL);
free(p);
}
}
dbus_connection_set_exit_on_disconnect(bus, FALSE);
if (!bus) {
bus = dbus_bus_get_private(t, error);
if (!bus)
return -EIO;
private = 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;
}

View file

@ -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) {
unlink("/run/systemd/private");
if (!(m->private_bus = dbus_server_listen("unix:path=/run/systemd/private", &error))) {
/* 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);
}
if (!m->private_bus) {
log_error("Failed to create private D-Bus server: %s", bus_error_message(&error));
r = -EIO;
goto fail;