fix(linux): let the uinput uid gate see the greeter that owns seat0

Input at a real greeter was rejected by our own authorization. Measured on Ubuntu
24.04 with gdm3: the root service logs

  Rejected unauthorized connection on uinput ipc channel:
  postfix=_uinput_control, peer_uid=Some(120), active_uid=None

and the greeter's `--server` gets ECONNRESET out of `setup_uinput`, so no uinput
device is ever created and neither keyboard nor mouse reaches the greeter.

uid 120 is gdm, the owner of the only active seat0 session. `active_uid` is None
because the uinput authorizer deliberately bypasses the service-loop cache and
takes a fresh seat0 lookup, and the fresh read hides a Wayland greeter by
construction. The cache-based gates do not have the problem: `Desktop::refresh`
fills it through the greeter-visible read, which is also why capture and config
sync work at a greeter while input does not.

So make the fresh read agree with the cache. It keeps the property the uinput gate
wants, a lookup that cannot be stale, and it still compares the peer against the
uid of the session that owns seat0 -- which at a greeter is the greeter.
This commit is contained in:
Mariano Abad
2026-08-08 14:21:45 -03:00
parent 7458e57665
commit 7582350511

View File

@@ -1109,6 +1109,11 @@ pub fn get_active_userid() -> String {
#[inline]
/// Returns the active uid from a fresh seat0 lookup, bypassing the service-loop cache.
pub fn get_active_userid_fresh() -> String {
// A Wayland greeter owns seat0 while it is up and the DRM backend serves it, so a uid gate that
// cannot see it rejects the greeter's own `--server`. `Desktop::refresh` reads it the same way.
#[cfg(feature = "drm")]
return get_values_of_seat0_with_gdm_wayland(&[1])[0].clone();
#[cfg(not(feature = "drm"))]
get_values_of_seat0(&[1])[0].clone()
}