ci / web (pull_request) Successful in 1m53s
ci / bun-nix (pull_request) Successful in 30s
ci / docs-drift (pull_request) Successful in 28s
android / android (pull_request) Successful in 5m44s
ci / rust-arm64 (pull_request) Successful in 5m59s
ci / docs-site (pull_request) Successful in 5m44s
ci / rust (pull_request) Successful in 15m20s
Second half of "the power menu does nothing during a stream", and an independent fault from the sleep veto: on the takeover flavors that STOP the display manager, the box is left with no active local session, and that is what logind's power actions are gated on. logind ships `power-off`/`reboot`/`suspend` as `allow_active: yes`. polkit decides "active" from the caller's own logind session and, for a caller that has none — every `systemd --user` unit, which is exactly what the managed gamescope session is — falls back to the user's elected DISPLAY session. logind elects that only from `user`/`greeter` class sessions, never from the user manager's own, so stopping the display manager removes the last candidate and all three actions drop to `auth_admin_keep`: an interactive password prompt, put to a non-interactive caller, on a screen that is switched off. On SteamOS-like boxes that is the call being refused. Steam does not ask logind for "Shut Down" at all — it writes $STEAMOS_STEAM_SHUTDOWN_SENTINEL and exits, and gamescope-session-plus runs a plain `poweroff` once Steam is gone. During a stream that wrapper is ours, in the session-less transient unit. Measured on Bazzite, 2026-08-24: the identical `pkcheck --action-id org.freedesktop.login1.power-off` from a `systemd --user` unit answers authorized with sddm up, and `auth_admin_keep` with sddm stopped — and answers authorized again, in that same stopped state, with this rule installed. Scope it to the (shipped-empty) `punktfunk` group, which is the same group the takeover's own root helper authorizes on: a takeover that stops a display manager cannot work without that helper, so this grants to exactly the population the fault reaches. The three actions are the three entries in Steam's power menu; the `-multiple-sessions` and `-ignore-inhibit` variants are deliberately left out.
42 lines
2.7 KiB
Plaintext
42 lines
2.7 KiB
Plaintext
// Members of the `punktfunk` group may power the box off, restart it, or put it to sleep even when
|
|
// the box has no ACTIVE LOCAL SESSION — which is exactly the state a display-manager takeover
|
|
// leaves it in for the length of a stream.
|
|
//
|
|
// Why this is needed at all: logind ships `power-off`/`reboot`/`suspend` as `allow_active: yes`,
|
|
// and polkit decides "active" from the caller's own logind session — falling back to the user's
|
|
// elected DISPLAY session when the caller has none, which is every `systemd --user` unit including
|
|
// the managed gamescope session. A takeover that STOPS the display manager removes that session
|
|
// (logind elects a display session only from `user`/`greeter` class ones, never from the user
|
|
// manager's), the fallback then finds nothing, and all three actions become `auth_admin_keep`: an
|
|
// interactive password prompt, asked of a non-interactive caller, on a screen that is switched off.
|
|
// Nothing surfaces the refusal, so the symptom is a power menu that does nothing at all.
|
|
//
|
|
// That menu is the reason this file exists. On SteamOS-like boxes Steam does not call logind for
|
|
// "Shut Down" — it writes `$STEAMOS_STEAM_SHUTDOWN_SENTINEL` and exits, and `gamescope-session-plus`
|
|
// runs a plain `poweroff` once Steam is gone. During a stream that wrapper is OURS, running in the
|
|
// session-less transient unit, so its `poweroff` is the call polkit refuses. Measured on Bazzite,
|
|
// 2026-08-24: the identical `pkcheck --action-id org.freedesktop.login1.power-off` from a
|
|
// `systemd --user` unit answers authorized with the display manager up, and `auth_admin_keep` with
|
|
// it stopped.
|
|
//
|
|
// The group ships EMPTY and joining it is a deliberate act. It is the same group the takeover's own
|
|
// root helper (`io.unom.punktfunk.dm-helper`) authorizes on, and a takeover that stops a display
|
|
// manager cannot work without that helper — so this grants to exactly the population the fault
|
|
// reaches, and to nobody else.
|
|
//
|
|
// Scope notes: the three actions are the three entries in Steam's power menu, so a grant that stops
|
|
// there authorizes "use the power menu on the box you are streaming from" and nothing else. The
|
|
// `-multiple-sessions` variants are deliberately NOT granted — a box with a second USER logged in
|
|
// still asks before it powers off under them — and neither are the `-ignore-inhibit` ones, which
|
|
// would let this override somebody else's block inhibitor rather than just our absent session.
|
|
polkit.addRule(function (action, subject) {
|
|
if (
|
|
(action.id == "org.freedesktop.login1.power-off" ||
|
|
action.id == "org.freedesktop.login1.reboot" ||
|
|
action.id == "org.freedesktop.login1.suspend") &&
|
|
subject.isInGroup("punktfunk")
|
|
) {
|
|
return polkit.Result.YES;
|
|
}
|
|
});
|