[systemd-devel] [PATCH v2 03/10] logind: add session controllers
A session usually has only a single compositor or other application that controls graphics and input devices on it. To avoid multiple applications from hijacking each other's devices or even using the devices in parallel, we add session controllers. A session controller is an application that manages a session. Specific API calls may be limited to controllers to avoid others from getting unprivileged access to restricted resources. A session becomes a controller by calling the RequestControl() dbus API call. It can drop it via ReleaseControl(). logind tracks bus-names to release the controller once an application closes the bus. We use the new bus-name tracking to do that. Note that during ReleaseControl() we need to check whether some other session also tracks the name before we remove it from the bus-name tracking list. Currently, we only allow one controller at a time. However, the public API does not enforce this restriction. So if it makes sense, we can allow multiple controllers in parallel later. Or we can add a scope parameter, which allows a different controller for graphics-devices, sound-devices and whatever you want. Note that currently you get -EBUSY if there is already a controller. You can force the RequestControl() call (root-only) to drop the current controller and recover the session during an emergency. To recover a seat, this is not needed, though. You can simply create a new session or force-activate it. To become a session controller, a dbus caller must either be root or the same user as the user of the session. This allows us to run a session compositor as user and we no longer need any CAP_SYS_ADMIN. --- src/login/logind-dbus.c | 8 +++ src/login/logind-session-dbus.c | 42 src/login/logind-session.c | 48 + src/login/logind-session.h | 6 ++ src/login/logind.c | 10 + 5 files changed, 114 insertions(+) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 5decf81..113a2b7 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2473,8 +2473,16 @@ DBusHandlerResult bus_message_filter( goto finish; } +/* drop all controllers owned by this name */ if (*old !*new (key = hashmap_remove(m-busnames, old))) { +Session *session; +Iterator i; + free(key); + +HASHMAP_FOREACH(session, m-sessions, i) +if (session_is_controller(session, old)) +session_drop_controller(session); } } diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 2cc4d85..b8b32cd 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -40,6 +40,10 @@ arg name=\who\ type=\s\/\n \ arg name=\signal\ type=\s\/\n\ /method\n \ + method name=\RequestControl\/\n \ + arg name=\force\ type=\b\/\n \ + /method\n \ + method name=\DropControl\/\n\ signal name=\Lock\/\n \ signal name=\Unlock\/\n \ property name=\Id\ type=\s\ access=\read\/\n\ @@ -366,6 +370,44 @@ static DBusHandlerResult session_message_dispatch( if (!reply) goto oom; +} else if (dbus_message_is_method_call(message, org.freedesktop.login1.Session, RequestControl)) { +dbus_bool_t force; +unsigned long ul; + +if (!dbus_message_get_args( +message, +error, +DBUS_TYPE_BOOLEAN, force, +DBUS_TYPE_INVALID)) +return bus_send_error_reply(connection, message, error, -EINVAL); + +ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error); +if (ul == (unsigned long) -1) +return bus_send_error_reply(connection, message, error, -EIO); + +if (ul != 0 (force || ul != s-user-uid)) +return bus_send_error_reply(connection, message, NULL, -EPERM); + +r = session_set_controller(s, bus_message_get_sender_with_fallback(message), force); +if (r 0) +return bus_send_error_reply(connection, message, NULL, r); + +reply =
Re: [systemd-devel] [PATCH v2 03/10] logind: add session controllers
On Tue, 17.09.13 17:39, David Herrmann (dh.herrm...@gmail.com) wrote: Please rename the bus calls to TakeControl()/ReleaseControl() (as discussed at the hackfest). Otherwise patch #2 and #3 look good to merge! A session usually has only a single compositor or other application that controls graphics and input devices on it. To avoid multiple applications from hijacking each other's devices or even using the devices in parallel, we add session controllers. A session controller is an application that manages a session. Specific API calls may be limited to controllers to avoid others from getting unprivileged access to restricted resources. A session becomes a controller by calling the RequestControl() dbus API call. It can drop it via ReleaseControl(). logind tracks bus-names to release the controller once an application closes the bus. We use the new bus-name tracking to do that. Note that during ReleaseControl() we need to check whether some other session also tracks the name before we remove it from the bus-name tracking list. Currently, we only allow one controller at a time. However, the public API does not enforce this restriction. So if it makes sense, we can allow multiple controllers in parallel later. Or we can add a scope parameter, which allows a different controller for graphics-devices, sound-devices and whatever you want. Note that currently you get -EBUSY if there is already a controller. You can force the RequestControl() call (root-only) to drop the current controller and recover the session during an emergency. To recover a seat, this is not needed, though. You can simply create a new session or force-activate it. To become a session controller, a dbus caller must either be root or the same user as the user of the session. This allows us to run a session compositor as user and we no longer need any CAP_SYS_ADMIN. --- src/login/logind-dbus.c | 8 +++ src/login/logind-session-dbus.c | 42 src/login/logind-session.c | 48 + src/login/logind-session.h | 6 ++ src/login/logind.c | 10 + 5 files changed, 114 insertions(+) diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 5decf81..113a2b7 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -2473,8 +2473,16 @@ DBusHandlerResult bus_message_filter( goto finish; } +/* drop all controllers owned by this name */ if (*old !*new (key = hashmap_remove(m-busnames, old))) { +Session *session; +Iterator i; + free(key); + +HASHMAP_FOREACH(session, m-sessions, i) +if (session_is_controller(session, old)) +session_drop_controller(session); } } diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 2cc4d85..b8b32cd 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -40,6 +40,10 @@ arg name=\who\ type=\s\/\n \ arg name=\signal\ type=\s\/\n\ /method\n \ + method name=\RequestControl\/\n \ + arg name=\force\ type=\b\/\n \ + /method\n \ + method name=\DropControl\/\n\ signal name=\Lock\/\n \ signal name=\Unlock\/\n \ property name=\Id\ type=\s\ access=\read\/\n\ @@ -366,6 +370,44 @@ static DBusHandlerResult session_message_dispatch( if (!reply) goto oom; +} else if (dbus_message_is_method_call(message, org.freedesktop.login1.Session, RequestControl)) { +dbus_bool_t force; +unsigned long ul; + +if (!dbus_message_get_args( +message, +error, +DBUS_TYPE_BOOLEAN, force, +DBUS_TYPE_INVALID)) +return bus_send_error_reply(connection, message, error, -EINVAL); + +ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error); +if (ul == (unsigned long) -1) +return bus_send_error_reply(connection, message, error, -EIO); + +if (ul != 0 (force || ul != s-user-uid)) +return
Re: [systemd-devel] [PATCH v2 03/10] logind: add session controllers
On Tue, 17.09.13 18:29, Lennart Poettering (lenn...@poettering.net) wrote: Please rename the bus calls to TakeControl()/ReleaseControl() (as discussed at the hackfest). Otherwise patch #2 and #3 look good to merge! Oh well, did the change myself now and commited! Thanks! Also commited #2, and #4. Lennart -- Lennart Poettering - Red Hat, Inc. ___ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel