drm: address the consumer review (login-screen uid, frame flow control, hotplug)

- Start the login-screen --server as the active seat0 greeter account instead
  of root, so the DRM capture GPU/EGL convert never loads the vendor GPU
  userspace in a privileged process. A genuine root graphical session has no
  lower uid to drop to and stays root, and if the greeter spawn fails we fall
  back to a root --server so the login screen stays remotable. Gated on the drm
  feature so the non-drm build is unchanged.
- Bound the number of frames in flight on the `_drm` channel: the consumer acks
  each frame it finishes converting and the producer only sends while it holds
  credit, waiting on the socket otherwise. Without this the producer kept
  writing descriptors into the socket faster than a slow convert drained them
  and the consumer worked through an ever-growing backlog of stale frames. A
  zero-byte read or write on the ack path is treated as a closed peer rather
  than as success.
- Forward a display list that became empty (last monitor unplugged) instead of
  dropping it, so the availability cache leaves Available rather than keep
  advertising removed displays.
- On a topology change, invalidate the Wayland geometry cache and reapply the
  uinput mouse range for the new layout. The refresh runs off the frame-receive
  loop and is coalesced across the per-display receivers, so a multi-monitor
  hotplug runs one worker and the final layout wins.
- Clear the prefer-CPU-convert hints on a topology change: display indices can
  be renumbered, so a hint learned for an old index no longer refers to the same
  physical display. Re-learned on the next convert failure.
- Report a non-DRM-backed display when the DRM list is shorter than the sync
  list or any entry is offline, covering the present-but-demoted case.
This commit is contained in:
Mariano Abad
2026-07-23 21:21:33 -03:00
parent dd6ee24833
commit 1fcc15488c
5 changed files with 232 additions and 15 deletions

View File

@@ -897,7 +897,34 @@ pub fn start_os_service() {
) {
stop_subprocess();
force_stop_server();
start_server(None, &mut server);
// Run the login-screen --server as the active seat0 session user (the greeter
// account) rather than root, so the DRM capture GPU/EGL convert never loads the
// vendor GPU userspace in a privileged process. is_login_wayland() matches a GDM or
// SDDM Wayland greeter (is_gdm_user covers both), and desktop.uid is that greeter's
// uid, so this drops to whichever greeter owns seat0. A greeter is_gdm_user does not
// recognize (e.g. LightDM) never reaches this branch -- it takes the unprivileged
// else-branch below already. A genuine root graphical session (username=="root")
// has no lower uid to drop to, so it stays root. Gated on the drm feature so the
// non-drm build stays byte-identical to upstream.
#[cfg(feature = "drm")]
let run_as_greeter = desktop.username != "root" && !desktop.uid.is_empty();
#[cfg(not(feature = "drm"))]
let run_as_greeter = false;
if run_as_greeter {
start_server(Some(&desktop), &mut server);
// If dropping to the greeter uid did not produce a running server (spawn/exec
// failure), fall back to a root --server so the login screen stays remotable
// instead of looping on a failing greeter spawn. This pays the GPU-in-root
// tradeoff only on that failure path, never in the normal greeter case.
if server.is_none() {
log::warn!(
"greeter --server did not start; falling back to a root --server"
);
start_server(None, &mut server);
}
} else {
start_server(None, &mut server);
}
}
} else if desktop.username != "" {
// try kill subprocess "--server"