Resolves #5. Covers SQLite persistence for validation records and boot-attempt counter, 120s clean-boot threshold, modprobe.d blacklist autoload gate, GRUB snapshot recovery entry, interactive validation via StartValidationRun D-Bus method, and daemon-managed DKMS integration.
5.3 KiB
ADR-006: Module Lifecycle Protocol — Validation, Boot-Count Guard, and Recovery
Status: Accepted
Date: 2026-07-31
Deciders: Bongbetic (solo developer)
Source: Task #5
Context
mjolnir-km is an out-of-tree kernel module on the sole reference machine (MSI Thin A15 B7UCX), co-resident with msi-ec. It implements a custom cpuidle governor and telemetry sampler (FR-070, FR-071). Three safety FRs govern its lifecycle: FR-077 (no autoload until validated), FR-078 (boot-count guard — 2 unclean boots disable autoload), and FR-079 (known-good kernel entry preserved as recovery path). The daemon owns the module lifecycle (ADR-001 step 3), and DKMS handles rebuild (ADR-004 AUTOINSTALL=yes).
Decision
Persistence: SQLite
Validation records and boot-attempt counters live in the daemon's SQLite store (ADR-001 step 6 opens before step 3 loads the module — no phase mismatch). Two tables:
module_validation—(kernel_version TEXT, module_version TEXT, validated_at INTEGER, validation_method TEXT). One row per validated kernel.boot_attempt—(boot_id TEXT PK, started_at INTEGER, clean INTEGER, autoload_enabled INTEGER).boot_idfrom/proc/sys/kernel/random/boot_id. Written on daemon startup before module load. DAU purge retains last 10 boots.
Clean-boot threshold: 120 seconds
Boot is clean when the daemon shuts down gracefully with the module loaded for ≥120 seconds. A kernel module governor fault typically manifests within 30–60s of selection — 120s provides 4× polling cycles of observed clean operation. Aligns with systemd TimeoutStartSec=90s. Covers the suspend/resume validation cycle in FR-077.
Autoload gate: modprobe.d blacklist
/etc/modprobe.d/mjolnir-km-autoload.conf containing blacklist mjolnir-km. Managed by the daemon:
- File exists → auto-load blocked (post-install default; after boot-count guard trips).
- File removed → auto-load permitted (after validation run or admin re-enables).
Explicit modprobe mjolnir-km by the daemon bypasses the blacklist (it's alias-resolution-only). No DKMS POST_INSTALL script — the daemon owns the policy. DKMS only builds; on first boot of a new kernel, the daemon detects no validation record and writes the blacklist before attempting load.
Known-good kernel entry: GRUB snapshot
just install-km creates a /etc/grub.d/40_mjolnir_recovery script that copies the current default GRUB entry (pre-Mjolnir kernel command line) as a new entry named "Mjolnir-Free (recovery)" with modprobe.blacklist=mjolnir-km appended. Re-runs on every update-grub, re-deriving the latest non-Mjolnir entry. Recovery notes at /usr/share/doc/mjolnir/RECOVERY.md reference it by name.
Validation run: interactive admin flow
FR-077 validation steps (load, governor register/deregister, suspend/resume, clean unload) are sequenced by the daemon via a new StartValidationRun D-Bus method (PolKit-guarded). The suspend/resume step requires admin acknowledgment — not automatable without user consent. The daemon emits ValidationStage signals:
- Admin invokes
mjolnirctl validateor GTK "Validate Module". - Daemon loads module, sends
GOV_SELECT→ verifies, sendsTELEM_SAMPLE→ verifies, sendsGOV_DESELECT→ verifies. - Daemon emits
ValidationStage("suspend_required"). Admin suspends manually. - Post-resume: daemon verifies boot_id unchanged, re-runs GOV_SELECT → TELEM_SAMPLE → GOV_DESELECT.
- Daemon unloads module, persists validation record, removes modprobe.d blacklist.
- Emits
ValidationStage("complete").
On failure at any step: daemon unloads module, keeps blacklist, emits ValidationStage("failed", reason).
User notification
Two channels for boot-count guard trip (FR-078):
- D-Bus
AutoloadDisabled("boot_count_guard")signal → GTK desktop notification (ADR-003). - CLI:
mjolnirctl statusshowsautoload: disabled (reason: 2 consecutive unclean boots).
Both direct admin to run mjolnirctl validate to re-validate.
Consequences
- Positive: Daemon owns the full lifecycle — no split-authority between DKMS hooks, systemd, and the daemon.
- Positive: modprobe.d blacklist is a one-file gate, trivial to inspect and to override in recovery.
- Positive: Validation is interactive — the admin sees each step and owns the suspend decision.
- Negative: Validation requires the admin to be present and to manually suspend — cannot be fully automated.
- Negative: The 120s clean-boot threshold means a developer who insmod/rmmods in <120s gets an unclean boot recorded; acceptable since developer boots won't trip the guard (it takes 2 consecutive unclean boots with autoload enabled, and dev boots don't have autoload set).
Related
- ADR-001: Component Architecture — startup sequencing step 3
- ADR-002: Netlink Protocol — GOV_SELECT/DESELECT/TELEM_SAMPLE commands
- ADR-003: D-Bus API Contract — AutoloadDisabled signal, ValidationStage signal added
- ADR-004: Build Sequencing — DKMS AUTOINSTALL, just install-km
- Netlink Protocol Spec — §8.3 validation run hooks
- SRS FR-070–079, FR-075, FR-076
- SRS RISK-001 (co-resident DKMS modules), RISK-005 (dev machine = test machine)