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:
co-authored by
Claude Opus 5
parent
8db5e8dd9f
commit
23dff0b7b4
+118
@@ -0,0 +1,118 @@
|
||||
# Lockdown
|
||||
|
||||
What a teacher can and cannot do to the machine, and where each of those
|
||||
answers lives.
|
||||
|
||||
Most of it is KDE's own Kiosk mechanism, in
|
||||
`/etc/ekklesia-classroom/xdg/kdeglobals`: no shell, no command line, no
|
||||
lock screen, no editable panel. That file is the first place to look, and
|
||||
lifting a restriction for maintenance is a one-line edit there followed by
|
||||
a session restart.
|
||||
|
||||
This page is about the part that is *not* in that file: ending or
|
||||
suspending the session.
|
||||
|
||||
## The escape this closed
|
||||
|
||||
A teacher pressed **Ctrl+Alt+Delete**, got Plasma's session screen, and
|
||||
hibernated the classroom computer from it. A hibernated room cannot be
|
||||
recovered by anybody standing in front of it who does not know where the
|
||||
power button is, which on a Sunday morning is everybody.
|
||||
|
||||
`[KDE Action Restrictions] logout=false` was already set and did not stop
|
||||
it, and the reason is worth keeping written down: that restriction governs
|
||||
**Plasma's own actions** — the entries plasmashell draws in a menu or an
|
||||
applet. Ctrl+Alt+Delete is not one of them. It is a KGlobalAccel shortcut
|
||||
registered by ksmserver, and pressing it asks D-Bus for the logout greeter
|
||||
without ever consulting a Plasma action. A restriction on a menu cannot
|
||||
see a key.
|
||||
|
||||
## Three layers
|
||||
|
||||
### 1. The key
|
||||
|
||||
`/etc/ekklesia-classroom/kglobalshortcutsrc` unbinds every ksmserver
|
||||
session action and PowerDevil's Sleep, Hibernate, PowerDown and PowerOff
|
||||
keys, with each entry marked `[$i]` so nothing writes them back.
|
||||
|
||||
It is **not** in `/etc/ekklesia-classroom/xdg` with the other settings, and
|
||||
that is deliberate. `kglobalacceld` opens `kglobalshortcutsrc` as a
|
||||
KConfig `SimpleConfig`: no cascade, no system directories. Measured — with
|
||||
the file in the cascade, `kreadconfig6` reported the chord unbound while
|
||||
the shortcut server went on answering Ctrl+Alt+Del.
|
||||
|
||||
So `classroom-desktop-reset` copies the package's copy into
|
||||
`~/.config/kglobalshortcutsrc` before the session's shortcut server
|
||||
starts, exactly as it does with the panel. Replacing the whole file costs
|
||||
nothing: KGlobalAccel puts every shortcut the file does not name back from
|
||||
each component's own defaults, and the entries the package does name are
|
||||
immutable, which is what stops it putting those back too.
|
||||
|
||||
The room's own chords are registered from their desktop entries and are
|
||||
unaffected — `converged-check` asserts both of them by key code after the
|
||||
replace.
|
||||
|
||||
### 2. The policy
|
||||
|
||||
`/usr/share/polkit-1/rules.d/49-ekklesia-classroom-sleep.rules` refuses
|
||||
`org.freedesktop.login1.suspend*` and `.hibernate*` **for the `classroom`
|
||||
user only**.
|
||||
|
||||
This is the layer that matters, because a key can be unbound and anything
|
||||
that reaches logind can still ask. PowerDevil, the greeter, `systemctl
|
||||
suspend` from the maintenance terminal and any future applet all go
|
||||
through these actions.
|
||||
|
||||
Hybrid sleep and suspend-then-hibernate have no polkit action of their own
|
||||
in systemd 257: logind authorises both through the hibernate action, so
|
||||
denying hibernate denies all three. The rule names the other two spellings
|
||||
anyway, in case a future systemd splits them out.
|
||||
|
||||
Refusing here rather than masking `sleep.target` is the point. Masking is
|
||||
machine-wide and would take suspend away from a technician's account too;
|
||||
worse, it would be invisible to Plasma, which would go on drawing a
|
||||
Hibernate button that silently failed. logind asks polkit whether *this
|
||||
user* may sleep, so a NO is both the enforcement and the supported way to
|
||||
tell the desktop not to offer it — `CanSuspend()` and `CanHibernate()`
|
||||
come back `no`.
|
||||
|
||||
Nothing here touches power-off or reboot, and nothing here applies to any
|
||||
other account.
|
||||
|
||||
### 3. The greeter
|
||||
|
||||
`/usr/local/share/dbus-1/services/org.kde.LogoutPrompt.service` shadows
|
||||
plasma-workspace's own activation file with `Exec=/bin/false`, the same
|
||||
mechanism the classroom already uses for the old notification daemon.
|
||||
|
||||
Ctrl+Alt+Delete does not draw anything itself; it asks D-Bus to start
|
||||
`ksmserver-logout-greeter`. Layer 1 removes the caller, this removes the
|
||||
callee, so any other caller finds nothing to start either.
|
||||
|
||||
## What is deliberately still there
|
||||
|
||||
- **Screen locking stays disabled.** None of this touches
|
||||
`kscreenlockerrc`, and `action/lock_screen=false` is unchanged. A
|
||||
classroom must never present a password prompt.
|
||||
- **The power button still does nothing** on a short press, at both the
|
||||
logind and PowerDevil layers, and a long firmware hold still cuts the
|
||||
power. That is the only recovery a person standing at a wedged machine
|
||||
has.
|
||||
- **Meta+Ctrl+Alt+Shift+K still opens the maintenance terminal**, and
|
||||
Meta+Ctrl+Alt+Shift+D still opens the display dialog.
|
||||
- **Reboot and shut down are not newly denied to anybody.** A teacher
|
||||
asking for either already lands on an administrator's password prompt,
|
||||
which they do not have; that behaviour is unchanged. A technician on SSH
|
||||
or at the maintenance terminal, with their own account, can still do all
|
||||
of it.
|
||||
|
||||
## Lifting it
|
||||
|
||||
For a technician who needs a classroom machine to suspend — a laptop on a
|
||||
bench, say — drop a file of the same name into `/etc/polkit-1/rules.d/`,
|
||||
which polkit reads ahead of the package's copy. Nothing needs rebuilding
|
||||
and nothing needs reinstalling.
|
||||
|
||||
To put the session screen back, remove the D-Bus shadow and the
|
||||
`kglobalshortcutsrc` entries; both are package files, so an update will
|
||||
restore them, which is the intended direction.
|
||||
Reference in New Issue
Block a user