reduce overlay RAM + kill .pyc AVC churn (TODO #16 item2, #17)

Two fixes from the booted-host overlay RAM audit (2026-07-03). The writable
root overlay (systemd.volatile=overlay, tmpfs) held 124.5 MiB of runtime
writes; almost all of it is runtime-regenerated state, not real fs deltas.

1. fapolicyd db_max_size 100 -> 50 (TODO #17). /var/lib/fapolicyd/data.mdb was
   100 MiB fully allocated (~80% of the overlay). fapolicyd's LMDB trust DB is
   rebuilt at boot onto the overlay, so db_max_size is a fixed RAM reservation.
   Sed it to 50 before the fapolicyd-cli --update rebuild. 50 was fapolicyd's
   long-time upstream default (covered a full workstation rpmdb), so it has
   headroom for this smaller image. Reclaims ~50 MiB.
   BENCH-VERIFY (STIG-critical exec guard): boot + kiosk + admin SSH + sudo +
   custom-binary exec must work (undersize -> MDB_MAP_FULL bricks exec).

2. .pyc invalidation fix (TODO #16 item 2). erofs -T 0 zeroes mtimes, so
   Python thinks every baked .pyc is stale and rewrites it into the overlay at
   runtime (wasting RAM + throwing lib_t write/unlink AVCs that flood the SIEM).
   Observed trigger: dnf-makecache.timer (~10 min post-boot) re-importing the
   dnf Python stack. Fix both ends: (a) compileall --invalidation-mode
   unchecked-hash over /usr/lib*/python3.* at the end of 2d (mtime-independent
   .pyc, no rewrite, also more reproducible); (b) mask dnf-makecache.timer next
   to the existing rhsmcertd mask (removes the trigger). Firewalld enablement
   (#16 items 1 & 3) still open.
This commit is contained in:
Audiobuzz
2026-07-03 04:03:36 +00:00
parent c0a08438b2
commit 796dfe9f4e
2 changed files with 92 additions and 0 deletions
+50
View File
@@ -1461,6 +1461,15 @@ tailoring; retires deviation-register #4).
unchecked-hash` over the Python trees BEFORE the erofs build → mtime-independent
`.pyc`, no rewrites, and MORE reproducible. (Worth doing regardless of firewalld —
it's the true root cause of the firewalld AVCs seen 2026-07-03.)
**[x] DONE (2026-07-03):** implemented in `diskless.pkr.hcl` — (a) the compileall
`--invalidation-mode unchecked-hash` pass over `/usr/lib*/python3.*` at the end of the
2d hygiene block (last step before erofs extraction), and (b) masked
`dnf-makecache.timer` next to the existing `rhsmcertd` mask (it was the observed ~10-min
post-boot trigger that re-imported the dnf Python stack). Confirmed live on a booted host
via the overlay audit: `dnf/libdnf/librepo/rhsm` `__pycache__` rewritten at boot+10min.
**BENCH-VERIFY:** after a rebuild, no more `.pyc` files appear in the overlay
(`find / -xdev -newermt '1980-01-01' -path '*__pycache__*'` empty) and the `lib_t`
`.pyc` AVCs stop in the SIEM. Items 1 & 3 (firewalld enablement + tailoring) still OPEN.
3. **Tailoring:** re-select the 4 firewalld rules.
**THE load-bearing bench gate (why #4 deferred it):** the NVMe/TCP root is an OUTBOUND
@@ -1469,3 +1478,44 @@ connection to `:4420` established in the initramfs BEFORE firewalld starts. Veri
default → should, but UNVERIFIED); a reconnect within `ctrl_loss_tmo` re-establishes
*through* the firewall; DHCP renew + MKA keepalives unaffected; SSH in; no AVCs; verity
hash reproducible. If it drops the root, that is the fleet-wide outage risk — gate hard.
## [~] 17. Cap fapolicyd trust-DB RAM (`db_max_size`) — biggest overlay consumer
**Finding (overlay RAM audit, 2026-07-03, host `cygnus-cruiser-99`):** the writable root
is `systemd.volatile=overlay` (a tmpfs). Enumerating runtime-written files via the `-T 0`
trick — every baked file has mtime = epoch, so anything newer is an overlay write:
```bash
sudo find / -xdev -type f -newermt '1980-01-01' -printf '%b\n' | awk '{s+=$1*512} END{print s/1048576" MiB"}'
```
showed **124.5 MiB** total, of which **`/var/lib/fapolicyd/data.mdb` = 100 MiB, FULLY
allocated** (`du` == `du --apparent-size`, not sparse) — **~80% of the entire overlay.**
fapolicyd's LMDB trust DB is rebuilt at boot onto the tmpfs overlay, so its `db_max_size`
(MB, in `/etc/fapolicyd/fapolicyd.conf`) is a **fixed RAM reservation**, not a ceiling it
grows into. The EL9 default is ~100; the minimal+kiosk trust set is a fraction of that.
**[x] DONE (2026-07-03):** `diskless.pkr.hcl` 2c-STIG-postfix now seds
`db_max_size = 50` into `fapolicyd.conf` BEFORE the `fapolicyd-cli --update` rebuild (so
the rebuilt db uses the smaller map). Value 50 chosen conservatively — it was fapolicyd's
upstream default for years and covered a FULL workstation rpmdb (larger than this image),
so it has real headroom. Reclaims ~50 MiB of overlay RAM.
**[ ] BENCH-VERIFY (STIG-critical — fapolicyd is the writable-overlay exec guard):**
1. Boot the rebuilt image; confirm kiosk renders, admin SSH (ECDSA) logs in, `sudo`
works, and custom binaries (`kiosk-session`, `fleet-hostapi`, `fleet-enrol`) still
execute — i.e. the trust DB rebuilt cleanly at 50 MiB with no `MDB_MAP_FULL`.
Undersizing bricks exec (login/kiosk) — that's the hard gate.
2. Re-run the overlay audit: `data.mdb` should now be ~50 MiB and total overlay ~75 MiB.
3. **Can go lower:** measure the real trust set with `fapolicyd-cli --dump | wc -l` on the
booted host; if the content is only ~15–25 MiB, 40 (or less) is safe and reclaims more.
**Secondary lever (free, already in flight):** the trust DB scales with trusted files, so
the kiosk weak-deps trim (commit `a193dc3`, ~100 fewer packages) shrinks the *actual*
`data.mdb` content — widening the headroom under `db_max_size`.
**Other overlay consumers noted (not fapolicyd, for context):** Chromium `/dev/shm`
(~38 MiB, its own tmpfs) + kiosk `/tmp/kiosk-profile` (on the root overlay here — `/tmp`
is NOT a separate tmpfs, ties to #15's mount separation); `/var/log/{messages,audit}`
grow unbounded in RAM (audit is local-only) — logrotate caps or SIEM offload on
long-lived hosts.