F-LEAK third attempt: band-scoped fenced destroy (v0.110.0)
The per-VM ACL is consumed by the destroy it authorises (PVE remove_vm_access, LXC.pm:906), so it works once per slot. Fourth root-fenced exception, band-enforced in sudoers literally + in code + at the caller. API destroy still tried first.
This commit is contained in:
@@ -1,3 +1,40 @@
|
||||
## v0.110.0 — F-LEAK, third attempt: the fourth root-fenced exception (2026-07-28)
|
||||
|
||||
**The band-scoped ACL fix (v1.21.0) is durable for exactly ONE use per slot, and the live check caught
|
||||
it.** After the first successful teardown of `990000`, `pveum acl list` showed **0 grants** at
|
||||
`/vms/990000`. Cause, confirmed in PVE's own source rather than inferred: the destroy path calls
|
||||
`PVE::AccessControl::remove_vm_access($vmid)` (`API2/LXC.pm:906`), which deletes
|
||||
`acl_root->children->vms->children->{$vmid}` — **every ACL at `/vms/<vmid>`** (`AccessControl.pm:1898`).
|
||||
|
||||
**The grant is consumed by the very operation it authorises.** After ten teardowns the whole band is
|
||||
ungranted and F-LEAK returns. A per-VM ACL is structurally the wrong tool here; the pool grant is
|
||||
durable only because it lives on a *pool* path, which `remove_vm_access` does not touch (it removes the
|
||||
guest's pool *membership*, not the pool's ACL).
|
||||
|
||||
**So this is attempt three, and it is the route the task offered as the alternative:** route the destroy
|
||||
through the same authority that already performs the create. `Privileged.DestroyScratchLXC` is the
|
||||
**fourth** root-fenced exception (previously exactly three: keyctl `pct create`, USB mount/fstab,
|
||||
SMART/sensors), and it is fenced harder than any of them:
|
||||
|
||||
| layer | enforcement |
|
||||
|---|---|
|
||||
| **sudoers** | `/usr/sbin/pct destroy 99000[0-9] --purge` — sudo matches the vmid **literally**. Even a compromised agent asking for `pct destroy 9201` is refused by sudo itself. |
|
||||
| **`DestroyScratchLXC`** | re-checks the band before exec; refuses an unconfigured or inverted band rather than defaulting |
|
||||
| **`teardownScratch`** | acts only on this journal entry's own scratch provenance |
|
||||
|
||||
None of the three is consumed by use, which is the property the ACL lacked. The API destroy is still
|
||||
tried **first** and remains the normal path; this is the fallback that makes teardown deterministic
|
||||
instead of once-per-slot. The v1.21.0 band ACLs stay provisioned — they make the common case need no
|
||||
privileged call at all.
|
||||
|
||||
**Ships with a sudoers change**, so `configs/felhom-agent.sudoers` must be deployed with the binary
|
||||
(`visudo -cf`: parsed OK).
|
||||
|
||||
Red-proofs 9 and 10, both observed failing: removing the band check →
|
||||
`REFUSAL FAILED: executed [pct destroy 9201 --purge] for out-of-band vmid 9201`; removing the
|
||||
unconfigured-band check → `an unconfigured band admitted vmid 0 and EXECUTED [pct destroy 0 --purge]`.
|
||||
The out-of-band table deliberately includes **9201**, the live customer guest on both demo boxes.
|
||||
|
||||
## v0.109.0 — the guest-power watchdog gets the observable it was shipped without (2026-07-28)
|
||||
|
||||
**Self-correction to v0.107.0, found by running the very check this session added elsewhere.** The new
|
||||
|
||||
Reference in New Issue
Block a user