From 7582350511c7092eb2b5558e400a439037997125 Mon Sep 17 00:00:00 2001 From: Mariano Abad Date: Sat, 8 Aug 2026 14:21:45 -0300 Subject: [PATCH] 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. --- src/platform/linux.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/platform/linux.rs b/src/platform/linux.rs index 200f19db5..6784b9a0f 100644 --- a/src/platform/linux.rs +++ b/src/platform/linux.rs @@ -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() }