Files
Classroom_Desktop/config/plasma/kglobalshortcutsrc
T
ekklesiaandClaude Opus 5 23dff0b7b4 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]>
2026-09-19 20:50:36 -05:00

87 lines
4.0 KiB
Plaintext

# The keys that end a classroom session, taken away.
#
# A teacher pressed Ctrl+Alt+Delete, got Plasma's session screen with
# Hibernate on it, and hibernated the room. This file is what closes that,
# and it is worth being precise about why the lockdown already in
# kdeglobals did not.
#
# [KDE Action Restrictions] logout=false stops *Plasma's own* logout
# actions — the ones plasmashell draws in a menu or an applet. The
# Ctrl+Alt+Delete chord is not one of those. It is a KGlobalAccel
# shortcut registered by ksmserver, and pressing it calls the logout
# greeter over D-Bus without ever asking a Plasma action whether it is
# allowed. A restriction on a menu cannot see a key.
#
# WHY THIS FILE IS NOT IN THE XDG DIRECTORY WITH THE OTHERS.
#
# Every other classroom setting is installed into
# /etc/ekklesia-classroom/xdg and reaches Plasma through KConfig's
# cascade. That was tried here first and it does not work, which was
# measured rather than reasoned about: with this file in the cascade,
# kreadconfig6 reported the chord as "none" while kglobalacceld went on
# answering Ctrl+Alt+Del. kglobalacceld opens kglobalshortcutsrc as a
# SimpleConfig — no cascade, no system directories, no immutability from
# anywhere but the file itself — so it reads exactly one file,
# ~/.config/kglobalshortcutsrc, and nothing else.
#
# So this is installed to /etc/ekklesia-classroom/kglobalshortcutsrc and
# classroom-desktop-reset copies it into the teacher's home before the
# session's shortcut server starts. That is the same thing the classroom
# already does with the panel: the file in the home directory is not
# state, it is a copy of the package, replaced at every login so that an
# update can always reach a room.
#
# KGlobalAccel stores every shortcut as
#
# Name=active,default,friendly name
#
# and repopulates whatever is missing from each component's registered
# defaults when that component starts — which is why replacing the whole
# file costs nothing: everything not named below comes straight back.
# Measured in the lab, including the maintenance chord, which is
# registered from its desktop entry and is bound again after the replace.
#
# Each key is marked [$i] — immutable — and that is what makes the
# replacement stick: KGlobalAccel writes this file constantly, and
# without the marker it would put the chord back the moment ksmserver
# registered its actions again.
#
# Per key rather than per group, deliberately. Marking
# [org_kde_powerdevil] immutable as a whole would also freeze the
# brightness and keyboard backlight keys, which a classroom has no reason
# to take away.
#
# The default column is set to none as well as the active one, so that
# "reset to default" is not a way back to the chord.
#
# This is one of three layers. The other two are the polkit rule that
# makes the sleep states unavailable to the classroom user at all, and the
# D-Bus service file that leaves the greeter itself with nothing to start.
[ksmserver]
# The chord itself.
Log Out[$i]=none,none,Show Logout Screen
# And every other way ksmserver offers to end the session. All of these
# ship unbound; they are written out so that a future Plasma release
# cannot introduce a default binding into a room without this file being
# updated too.
Log Out Without Confirmation[$i]=none,none,Log Out Without Confirmation
LogOut[$i]=none,none,Log Out
Halt Without Confirmation[$i]=none,none,Shut Down Without Confirmation
Reboot[$i]=none,none,Reboot
Reboot Without Confirmation[$i]=none,none,Reboot Without Confirmation
Shut Down[$i]=none,none,Shut Down
[org_kde_powerdevil]
# Sleep and Hibernate are bound by default to the XF86Sleep and
# XF86Hibernate keys, which a classroom keyboard may well have. PowerDown
# and PowerOff are the same story for XF86PowerDown and XF86PowerOff.
#
# The power *button* is already ignored at two layers; these are the
# keyboard keys of the same name, which are a different path and were
# never covered.
Sleep[$i]=none,none,Suspend
Hibernate[$i]=none,none,Hibernate
PowerDown[$i]=none,none,Power Down
PowerOff[$i]=none,none,Power Off