dbus: listen on private sockets in user mode too
This commit is contained in:
parent
8fef765900
commit
be81bfc4a7
|
@ -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;
|
||||
}
|
||||
|
|
39
src/dbus.c
39
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) {
|
||||
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue