docs/stig-deviations #15: fapolicyd overlay watch VERIFIED enforcing (2026-07-04)

Bench pass on fapolicyd-tmpfs-12043d3 / comet-beacon-54: permissive=0, watch_fs has
overlay, / and /tmp both overlayfs; novel-hash /tmp binary DENIED (FANOTIFY resp=2,
obj_trust=0, exit=126); empty deny sweep = zero false denials (kiosk/weston/chromium/
NM-dispatcher all trusted, admin SSH+sudo work under staff_t). The exec guard went
from effectively OFF to enforcing on the whole overlay root, nothing legit broken.

Also records the scope caveat: integrity=none path-trust closes the UNTRUSTED-PATH
half (proven) but not the MODIFIED-TRUSTED-PATH half — an overlayfs copy-up of a
trusted path (e.g. /usr/bin/bash) lands a same-path tmpfs copy outside dm-verity that
path-trust still trusts. Closing it needs integrity=sha256 or an un-shadowable /usr
(TODO #15, preferred).
This commit is contained in:
Audiobuzz
2026-07-04 02:52:04 +00:00
parent bdc7e6b234
commit e27f068aaf
+32
View File
@@ -216,6 +216,38 @@ still work (nothing legit is untrusted — the 4 custom binaries + rpmdb are tru
a novel `/tmp` binary is now **blocked** (EPERM), and no new AVCs (extend the `.te` a novel `/tmp` binary is now **blocked** (EPERM), and no new AVCs (extend the `.te`
if any). `enable_stig=false` is the escape hatch if it regresses the boot/secure path. if any). `enable_stig=false` is the escape hatch if it regresses the boot/secure path.
**VERIFIED 2026-07-04 (build `fapolicyd-tmpfs-12043d3`, host `comet-beacon-54`) —
enforcing, no false positives.** `fapolicyd active (running)`, `permissive = 0`,
`watch_fs = ...,overlay` (the fix took), `stat -f / /tmp` → both `overlayfs` (so the
test hits the overlay rule, not the pre-existing tmpfs one). A novel-hash binary
(`cp /bin/true /tmp/n; printf '\0' >>/tmp/n`) was **denied**: `bash: /tmp/n: Operation
not permitted`, `exit=126`, and the audit record confirms fapolicyd did it —
`type=FANOTIFY ... resp=2` (FAN_DENY) `obj_trust=0` (target not in trust db). The
**deny sweep was empty** (`journalctl -t fapolicyd -b | grep dec=deny` → nothing),
i.e. **zero false denials**: kiosk-session/weston/chromium + the NM dispatcher scripts
all ran trusted; admin SSH + `sudo` worked under `staff_u:staff_r:staff_t`. So the
exec guard went from **effectively OFF** (pre-fix, overlay unwatched) to **enforcing
on the whole overlay root** with nothing legit broken. My NM-dispatcher false-denial
worry did not materialise.
**Scope caveat — this closes the UNTRUSTED-PATH half, not the MODIFIED-TRUSTED-PATH
half.** With `integrity = none`, trust is by **path**, so watching the overlay blocks
a *new* file at an *untrusted* path (`/tmp/n`) — proven above. It does **not** catch a
*trusted* path whose **content** was swapped: writing to e.g. `/usr/bin/bash` triggers
an overlayfs **copy-up** into the tmpfs upper — same path, new inode, **outside
dm-verity's coverage** (verity only protects the erofs lower, which is now shadowed) —
and the path-based rule still trusts it. Closing that residual gap needs either
`integrity = sha256` (fapolicyd re-hashes at exec, content ≠ trust-db hash → deny; the
rpmdb backend already carries SHA-256 digests, so it's a one-line `fapolicyd.conf`
change — cost is per-exec userspace hashing, partly redundant with verity on the
un-tampered lower) **or** an **un-shadowable `/usr`** so copy-up can't happen at all
(read-only mount → write fails EROFS, no tmpfs copy is ever created; path-trust becomes
sound again). The latter is tracked as **TODO #15** ("scope root overlay to per-subtree
tmpfs — un-shadowable `/usr`") and is the preferred fix since it removes the attack
surface rather than detecting abuse of it. Requires a write primitive to a root-owned
path either way (already-privileged context), which is fapolicyd's defense-in-depth
threat model — not an unprivileged bypass.
## Things that are NOT deviations (kept / enforced) ## Things that are NOT deviations (kept / enforced)
- **SELinux enforcing** (`selinux --enforcing`; labels preserved into the erofs). - **SELinux enforcing** (`selinux --enforcing`; labels preserved into the erofs).