Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

I16 · No automatic revert, rollback, or boot fallback selects a generation below the security …

planarian @ a924e09 · Spec v4.6 · snapshot main · all versions

No automatic revert, rollback, or boot fallback selects a generation below the security floor; going below it requires administrator approval (§12e). The floor is derived from the whole system closure (§12e); a fix outside the inspected set does not move it.

— SPEC §7

StatusProof phased:aGym
ProvedA (proof of the decide and target-selection parts; the bootloader part by test)2 : 3 (baseline 2 : 3, not degraded)5 entries, 5 must-pass

How it is proved

2 obligations, in crates/policy/src/proofs.rs; every one is checked on every CI run.

ObligationKindWhat it guaranteesSource
i16_below_floor_needs_administratorproof fnI16 (the decide part): a transition whose target generation is below the security floor is AskFirst for an administrator, or refused, whatever the autonomy setting, the transition kind, or the caller.proofs.rs:161
administrator_class_only_on_ask_firstproof fnAn Administrator approver class only ever comes with AskFirst.proofs.rs:170

What it rests on

If any of these is false, the proof no longer describes the real machine.

IdAssumptionKindAlso relied on by
V1vstd’s specifications of Vec, String::as_str, str::unicode_len, str::get_charProof-validityI5, I10, I11, I19, I21, I22
V2Value is an opaque external type (external_type_specification); nothing about it is assumedProof-validityI5, I11, I21
P3publish_boot and the override promotion rename are idempotentPlatformI1, I23

Every proof also rests on V7 (The specifications the proofs prove against (decide_spec, step_spec, inv, chained, the lemma statements) say what the SPEC’s English means), V8 (Verus is sound: what it reports verified holds of the code), V9 (Z3, the solver Verus calls, is sound), V10 (rustc compiles the verified code to a program with the semantics Verus checked).

How it is tested

EntryHarnessWhat it doesExpectsLatest verdict
en-i16-boot-fallback-respects-floorfakeAfter a security update raises the floor, the machine restarts and the boot fails. The automatic fallback does not select a generation below the floor: the boot default and the generation that boots are the floor.boot_default: candidate; generation: candidate; security_floor: candidatefake: PASS
floor-manual-rollback-needs-adminfakeAfter the security update, an administrator asks to roll back below the floor: AskFirst for an Administrator approver. The proposer cannot approve it (I19); root at a terminal can.generation: base; security_floor: candidate; txn: Committed Rollbackfake: PASS
floor-moves-via-watchdogfakeThe daemon is killed once the security update is Promoted and stays down; the watchdog completes the commit. The floor moves to the fixing generation: the floor record is part of the commit, whoever writes Committed.security_floor: candidate; txn: Committed ApplyChangefake: PASS
floor-revert-blockedfakeA security update (gym-vulnlib 1.0 → 1.1, the old build carries knownVulnerabilities) commits and raises the floor. gym-web then crashes and fails every restart. The only rollback target, known_good, is below the floor: no Rollback runs, the incident escalates with RevertBlockedByFloor, and the boot default stays at the floor.boot_default: candidate; escalation: RevertBlockedByFloor; generation: candidate; incident: service:gym-web; invariants: I1, I16; security_floor: candidate; txn: Committed ApplyChange, Rollbackfake: PASS
floor-service-package-fixvmA change whose only security fix is in a service’s package (gym-vulnsvc 1.0 -> 1.1; services.gym-vulnsvc.package, never in environment.systemPackages) commits. The security floor moves to it: the inspected set is the configuration’s whole package set, not environment.systemPackages.security_floor: candidate; txn: Committed ApplyChangeVM: not run in this build

Known limits

BypassRouteSeverityStatusCloses in
B-19A package referenced only by a store-path string (an ExecStart= naming /nix/store/… directly, a script’s interpolated path) has no meta to read at evaluation, so a fix to it does not move the security floorMediumOpenB
X-1Root edits the store, /boot, the binaries, the journal or the posture stateAcceptedAcceptedE
X-2A nixos-rebuild outside PlanarianAcceptedAcceptedC
X-4Physical accessAcceptedAcceptedE
X-6The supply chain: nixpkgs content, cache signatures, input-addressed store pathsAcceptedAccepted—
X-7Backends report success falsely; systemd or the kernel misbehave (P1, P6, P8)AcceptedAcceptedD, E

History

SpecChange
v4.4Invariants I16 (security floor), I17 (administrator set non-empty), I18 (hash-chained journal), I19 (no self-approval, no self-escalation), I20 (no agent without the monitor)
v4.4Phase A proof targets add I16 (in decide and target selection) and I19
v4.4rule 4’s preserve list extended to I10–I20
v4.5I16 states the inspected set (B-2)

See also

§12e · planarian_policy::proofs in rustdoc