Add WIP and notes for fallbackdm

This commit is contained in:
Johannes Leupolz 2025-12-22 19:59:31 +00:00
parent 4fbb4d7389
commit 77c3452bbb
4 changed files with 257 additions and 56 deletions

View file

@ -487,59 +487,6 @@ The chosen approach offers the best balance between correctness, portability, an
---
## **3.11 VT Guarding for Headless / No-Compositor Systems**
### **Decision**
When **no X11 or Wayland session is active**, `vuinputd` relies on a small, separate **VT-guard daemon** to own the currently active Virtual Terminal (VT) and switch it into **graphics mode (`KD_GRAPHICS`)**.
If an X11 or Wayland compositor is running, **no VT guard is required**, as the compositor already owns a VT and has disabled the VT keyboard handler.
The VT-guard:
* runs in the foreground
* opens the active VT (`/dev/tty`)
* prints an informational notice
* switches the VT to `KD_GRAPHICS`
* registers for VT release notifications
* restores `KD_TEXT` and exits on VT switch
It does not access evdev, uinput, or interpret key events.
### **Rationale**
On systems without a graphical session, keyboard input reaches `getty` via the **VT keyboard handler**, independent of evdev.
Switching the VT to `KD_GRAPHICS` disables this path and effectively starves `getty` on that VT.
This mirrors compositor behavior (Xorg / Wayland) without requiring rendering, DRM, or input stack integration.
### **Designed Behavior: VT Switching Is Allowed**
VT switching (e.g. `Ctrl+Alt+Fn`) is **intentionally not blocked**.
This preserves a recovery path:
* users can switch to another VT
* `getty` remains accessible for local login
* physical access always overrides remote control
On VT switch, the VT-guard restores `KD_TEXT` and exits cleanly.
### **Constraints and Guarantees**
The VT-guard guarantees:
* the active VT does not accept keyboard input
* `getty` is effectively disabled on that VT
* normal console behavior resumes on VT switch
### **Alternatives Considered**
* **Blocking VT switching**
Rejected to preserve local recovery.
---
## **3.11 Fallback Graphical Session (`fallbackdm`)**
### **Problem Statement**
@ -620,6 +567,8 @@ Conceptually, `fallbackdm` acts as a **headless placeholder graphical session**
* **Disabling gettys or VT switching globally**
Rejected to preserve emergency local access and standard Linux behavior.
* **Depending on a full display manager**
Rejected, as this may require dummy display devices in headless configurations and adds unnecessary complexity.
---

View file

@ -225,7 +225,111 @@ Sample output from `journalctl` showing vuinputd output:
---
## 7. Troubleshooting
## 7. Handling Phantom Input Events Caused by VTs
On Linux systems without an active graphical session (X11 or Wayland), **virtual terminals (VTs)** remain in text mode (`KD_TEXT`) and continue to process keyboard input via the kernel VT keyboard handler.
This can lead to *phantom input events*, where injected or forwarded input (e.g. via `vuinputd`) unintentionally reaches:
* `getty` login prompts
* inactive consoles
* kernel VT hotkeys (e.g. `Ctrl+Alt+Fn`)
The following approaches can be used to prevent or mitigate this behavior.
### Solution 1: Use KMSCON (DRM/KMS-based console)
A robust solution is to replace the kernel VT text console with a **DRM/KMS-based console** such as `kmscon`.
#### How it helps
* The kernel VT is no longer responsible for input handling
* Keyboard input is processed via evdev, not the VT layer
* Seat assignment is respected:
* devices on non-default seats (e.g. `seat_vuinput`) are ignored
* Phantom input events do not reach `getty`
#### Notes
* Requires DRM/KMS availability
* On most real GPUs, the DRM device remains available even when no monitor is connected and enters a hotplug-waiting state
* For headless systems, a virtual KMS device can be used:
```bash
modprobe vkms
```
#### Trade-offs
* Additional dependencies (DRM, kmscon)
* Not always desired for minimal or embedded systems
### Solution 2: VT Guard Mode (`--vt-guard`)
`vuinputd` can be started with the `--vt-guard` flag to explicitly neutralize VT input handling.
#### How it works
At startup, `vuinputd` performs a minimal VT operation such as:
* switching the active VT into graphics mode (`KD_GRAPHICS`), or
* disabling the kernel keyboard processing for that VT
This is done via direct VT ioctls (e.g. `KDSETMODE`), ensuring that:
* the kernel VT keyboard handler is inactive
* `getty` does not receive injected input events
#### Characteristics
* Very lightweight
* No DRM, compositor, or additional services required
* Effective even on fully headless systems
#### Caveats
* Relies on low-level VT ioctls
* Considered **hacky**, but intentionally minimal
* Bypasses higher-level session management
### Solution 3: fallbackdm (Work in Progress)
`fallbackdm` is an experimental, lightweight **logind-integrated fallback display manager**.
#### Intended behavior
* Starts only when no graphical session is active
* Registers a proper `greeter` session with `systemd-logind`
* Takes ownership of a VT and switches it to `KD_GRAPHICS`
* Prevents `getty` and the VT keyboard handler from receiving input
* Leaves other VTs untouched for emergency local access
#### Advantages
* Clean integration with `systemd-logind`
* No direct VT hacks
* Compatible with standard Linux session semantics
* Designed to coexist with real display managers
#### Status
* Currently under development
* Intended as the long-term, principled solution
### Summary
| Solution | Headless | Lightweight | logind-aware | Recommended for |
| ------------ | --------- | ----------- | ------------ | ---------------------------- |
| KMSCON | ⚠️ (vkms) | ❌ | ✅ | Full console replacement |
| `--vt-guard` | ✅ | ✅ | ❌ | Minimal setups |
| fallbackdm | ✅ | ⚠️ | ✅ | Long-term, clean integration |
Choose the approach that best fits your system constraints and deployment model.
---
## 8. Troubleshooting
| Symptom | Possible Cause | Fix |
| --------------------------- | ------------------------------------ | ------------------------------------------------- |
@ -246,7 +350,7 @@ Dez 14 21:33:17 wohnzimmer vuinputd[2172719]: called `Result::unwrap()` on an `E
Ensure /dev and /run are writable in the container. If in doubt, use tmpfs.
---
## 8. Notes and Advanced Topics
## 9. Notes and Advanced Topics
* You can safely run **multiple containers**.
* Devices are automatically cleaned up when the container stops.
@ -258,7 +362,7 @@ Ensure /dev and /run are writable in the container. If in doubt, use tmpfs.
---
## 9. References
## 10. References
* [mkosi manual](https://github.com/systemd/mkosi/blob/main/mkosi/resources/man/mkosi.1.md)
* [Docker device rules documentation](https://docs.docker.com/engine/reference/run/#device-cgroup-rule)

147
fallbackdm/README.md Normal file
View file

@ -0,0 +1,147 @@
# fallbackdm
> This crate is WIP and has not released any source, yet.
**fallbackdm** is a minimal, headless display manager that exists solely to **own a seat and VT when no graphical session is running**.
It prevents unintended keyboard input from reaching `getty` or the kernel VT layer by registering a proper **greeter session** with `systemd-logind`, activating a VT, and switching it to graphics mode — without starting X11 or Wayland.
This is primarily useful for **kiosk setups, remote desktop systems, or input-virtualization scenarios** where no local user interaction is intended, but correct VT semantics must still be preserved.
---
## Problem Statement
On modern Linux systems:
* Virtual terminals (VTs) still exist and have a kernel keyboard handler
* If **no graphical session is active**, `getty` will attach to a VT
* Input injected via `uinput` or forwarded from remote systems may:
* Trigger `Ctrl+Alt+Fn`
* Wake or interfere with `getty`
* Cause VT switches or text-mode interaction
Graphical compositors avoid this by:
* Registering a session with `systemd-logind`
* Owning a VT
* Switching it to `KD_GRAPHICS`
But when **no compositor or greeter is running**, nothing owns the VT.
**fallbackdm fills exactly this gap.**
---
## What fallbackdm Does
* Registers a **`greeter` session** via PAM + `pam_systemd`
* Acquires a seat using **libseat**
* Activates a VT and switches it to graphics mode
* Keeps the session alive while no real graphical session exists
* Displays nothing and launches no compositor
Once a real display manager or compositor starts, it naturally replaces `fallbackdm`.
---
## What fallbackdm Does *Not* Do
* ❌ No X11
* ❌ No Wayland
* ❌ No greeter UI
* ❌ No input filtering (by design)
* ❌ No Device Ownership Required: Unlike a real compositor, `fallbackdm` does not need to open `/dev/dri/cardX` or `/dev/input/event*` to do its job. It only needs the TTY. This minimizes the attack surface significantly.
It only ensures **correct session, seat, and VT ownership**.
---
## When You Need This
You **do not need fallbackdm** if:
* X11 or Wayland is already running
* A display manager (gdm, sddm, greetd, etc.) is active
You **do need fallbackdm** if:
* The system boots without a graphical stack
* Input devices (especially `uinput`) must not reach `getty`
* You rely on logind-correct VT behavior without a real compositor
---
## Architecture Overview
```
fallbackdm
├─ PAM session (class=greeter)
├─ pam_systemd
├─ libseat
│ └─ seatd or systemd-logind backend
└─ VT activation + KD_GRAPHICS
```
This mirrors what real display managers do — just without launching anything graphical.
---
## PAM Configuration
Create `/etc/pam.d/fallbackdm`:
```
session required pam_systemd.so class=greeter
```
This is mandatory. Without it, logind will not track the session.
---
## systemd Service Example
```ini
[Unit]
Description=Fallback Display Manager
After=systemd-user-sessions.service
ConditionPathExists=!/run/graphical-session-active
[Service]
ExecStart=/usr/bin/fallbackdm
PAMName=fallbackdm
Restart=always
[Install]
WantedBy=multi-user.target
```
> The condition is optional and can be replaced with more advanced logic later.
---
## Relationship to Other Projects
* **Display managers (gdm, sddm, greetd)**
Full login stacks with UI and session spawning.
* **Greeters (gtkgreet, tuigreet)**
UI components launched *by* a display manager.
* **fallbackdm**
A *headless*, compatibility-focused DM whose only job is to own the seat.
---
## Future Ideas
* Optional status output on the VT
* Signaling input-forwarding daemons (e.g. `vuinputd`)
* Conditional exit when a real session becomes active
---
## License
MIT

View file

@ -0,0 +1 @@
session required pam_systemd.so class=greeter