feat: close the chord that let a teacher hibernate the room

Ctrl+Alt+Delete opened Plasma's session screen and a teacher hibernated a
classroom computer from it. A hibernated room cannot be recovered by
anybody standing in front of it, which on a Sunday morning is everybody.

logout=false was already set and did not stop it. That restriction
governs Plasma's own actions — what plasmashell draws in a menu or an
applet. The chord is a KGlobalAccel shortcut registered by ksmserver and
it asks D-Bus for the greeter without consulting a Plasma action at all.
A restriction on a menu cannot see a key.

Three layers, because each one alone has a way past it.

The key. kglobalshortcutsrc unbinds every ksmserver session action and
PowerDevil's Sleep, Hibernate, PowerDown and PowerOff, each entry marked
immutable. It is deliberately not in the xdg directory with the other
settings: kglobalacceld opens that file as a SimpleConfig, so it reads
one file in the teacher's home and no system directory at all. Measured —
with it in the cascade, kreadconfig6 reported the chord unbound while the
shortcut server went on answering Ctrl+Alt+Del. classroom-desktop-reset
copies the package's copy into place before the shortcut server starts,
the same way the panel is copied out of the package at every login.

The policy. A polkit rule refuses login1.suspend* and .hibernate* for the
classroom user and for nobody else. This is the layer that matters:
a key can be unbound and anything reaching logind can still ask.
Refusing here rather than masking sleep.target keeps a technician's own
account working, and is also what tells Plasma to stop drawing the
button — CanSuspend and CanHibernate come back no. Hybrid sleep and
suspend-then-hibernate have no action of their own in systemd 257; both
are authorised through hibernate, so denying it denies all three.

The greeter. Its D-Bus activation is shadowed with /bin/false, the same
mechanism already used for the old notification daemon. Layer one removes
the caller, this removes the callee.

Measured in the lab, from the package, after a reboot: the escape
reproduced first with the shadow removed — the greeter really does start
— and then refused, exited 1, with it back. The chord reports nothing
bound. systemctl suspend as the classroom user is denied. The maintenance
chord and the display chord both still answer, by key code, after the
shortcut file is replaced wholesale. A root process may still suspend,
hibernate, reboot and power off. 182 checks pass across a logout and back.

Screen locking stays disabled, the power button still does nothing, and
reboot and shut down are not newly denied to anybody.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
ekklesia
2026-09-19 20:50:36 -05:00
co-authored by Claude Opus 5
parent 8db5e8dd9f
commit 23dff0b7b4
8 changed files with 467 additions and 0 deletions
+31
View File
@@ -123,6 +123,37 @@ if [[ -f "$CONFIG_HOME/kdeglobals" ]]; then
esac
fi
# THE KEYS THAT END A SESSION.
#
# Ctrl+Alt+Delete opened Plasma's session screen in a real classroom and a
# teacher hibernated the machine from it. The chord is a KGlobalAccel
# shortcut, and KGlobalAccel is the one part of Plasma the classroom
# cannot reach through KConfig's cascade: kglobalacceld opens
# kglobalshortcutsrc as a SimpleConfig, so it reads this one file in the
# teacher's home and no system directory at all. Measured — with the
# settings in /etc/ekklesia-classroom/xdg, kreadconfig6 reported the chord
# unbound while the shortcut server went on answering Ctrl+Alt+Del.
#
# So the package's copy is put there directly, before the shortcut server
# starts, exactly as the panel is. Nothing of a teacher's is lost: there
# is no settings application in this room, and KGlobalAccel puts every
# shortcut that is not named in the file back from its own defaults when
# each component registers. The entries the package does name are marked
# immutable, which is what stops it putting those back too.
SHORTCUTS=/etc/ekklesia-classroom/kglobalshortcutsrc
if [[ -r "$SHORTCUTS" ]]; then
if cmp -s "$SHORTCUTS" "$CONFIG_HOME/kglobalshortcutsrc"; then
say "session shortcuts already the package's"
else
install -m 600 "$SHORTCUTS" "$CONFIG_HOME/kglobalshortcutsrc"
say "session shortcuts replaced with the package's"
fi
else
say "WARNING: $SHORTCUTS is missing — Ctrl+Alt+Delete may open the"
say " session screen this room is not supposed to have"
fi
# The room's power behaviour is policy, not preference: never sleep, never
# dim, never lock. PowerDevil loads an idle action when it finds a group
# for it, and the merged view of this file is where such a group could