merge: a checker for the deprovision spec, and the trap that makes it pass for free
This commit is contained in:
@@ -146,8 +146,28 @@ All of these must hold for the freed uid *and* its freed subuid range:
|
||||
- `/run/user/<uid>` absent
|
||||
- no processes owned by the uid
|
||||
|
||||
Worth extracting as `assertUidFree(uid, subuidRange)` and reusing it as the post-condition of the function and
|
||||
as a test.
|
||||
`scripts/assert-uid-free.sh` implements exactly this, deliberately **outside** the function: a checker the
|
||||
implementation calls is a restatement of its own beliefs, not an audit. Two modes, and the split matters —
|
||||
|
||||
```
|
||||
./scripts/assert-uid-free.sh --capture green # BEFORE: prints "green 1001 165536 65536"
|
||||
sudo ./scripts/assert-uid-free.sh --check green 1001 165536 65536 # AFTER: exit 1 unless clean
|
||||
```
|
||||
|
||||
The range has to be captured **before** deletion, because `userdel` removes the `/etc/subuid` entry with the
|
||||
account. After that there is no way to ask what range it held — and a check that silently skips that half is
|
||||
the exact failure this section exists to prevent.
|
||||
|
||||
**The subuid check passes vacuously on most accounts, and that is a trap.** Container files are owned by a
|
||||
mapped id only when a process inside the container runs as a NON-root user; an image whose files are root-owned
|
||||
maps to the member's own uid and leaves nothing in the range. Measured on green after a night of real use —
|
||||
`claude` installed, images pulled, transcripts written — the range check found **zero** files and passed
|
||||
without testing anything.
|
||||
|
||||
To build a specimen that actually exercises it, run a container whose process writes as a non-root user. The
|
||||
`postgres:18-alpine` case from the same night is the natural one: its entrypoint drops to uid 70, and the data
|
||||
directory came out owned by `subuid_start + 70` on the host. Verify the range check *fails* on that tree before
|
||||
trusting it to pass on a cleaned one.
|
||||
|
||||
**Trap for the verifier:** do not use `sudo -u <user> …` to check anything after step 2. Creating a session
|
||||
starts a user manager and recreates `/run/user/<uid>`, so the check would undo the step it is verifying.
|
||||
|
||||
Reference in New Issue
Block a user