Path-based matching in `pkg/bpf/lsm` (`bpf_d_path` keyed on the kernel-resolved path) already defeats symlink/`/proc/self/root`-style indirection, and default-deny already closes the "copy a binary to an unlisted path" dodge (see #171). The gap neither closes: an attacker who overwrites the content at an already allow-listed path (e.g. replaces `/usr/bin/kubectl` in place) is still permitted, because the match is on path, not on what's actually in the file.
Recommended phasing
Phase 0 — platform gate
Add an `fs-verity`-support platform check alongside the existing BPF-LSM gate (`docs/users/platforms.md`). No enforcement change yet; this only tells us where the feature can ship at all.
Phase 1 — fs-verity digest matching, scoped narrow
- Use the existing `bpf_get_fsverity_digest()` BPF kfunc from a sleepable LSM hook to fetch a file's precomputed content digest — no in-kernel hashing, no new crypto helper needed.
- Extend `pkg/compiler` with a digest value type (`sha256:`) parsed the same way `pathvalue.go` parses paths, and a parallel `banned`/`allowed` digest map in `pkg/bpf/lsm`, composed as OR with the existing path-based decision.
- Ship scoped to a small, explicit set of high-value paths (agent CLIs, `kubectl`, similar) that a policy author opts into — not a general default-on mechanism.
- Requires the target files to have `fs-verity` enabled (and therefore immutable) before enrollment; this needs an explicit build-time step (`fsverity enable`, or a filesystem/image format that does it automatically), which is a real deployment constraint to document up front, not discover later.
Phase 2 — evaluate before going further
- Decide whether to extend digest matching beyond the narrow allow-list case, based on real usage from Phase 1.
- Evaluate whether wiring into IMA/EVM's existing measurement + appraisal subsystem is less work than maintaining a bespoke digest map, given IMA already solves system-wide content measurement — a decision worth making with data, not speculatively.
- A userspace-hash-and-cache fallback (hash unenrolled files off the hot path, cache by `(dev, inode)`, invalidate on write) is only worth building if fs-verity turns out to be infeasible on target platforms — it reintroduces a bootstrap TOCTOU window and a cache-invalidation surface that fs-verity avoids by construction, so it should not be the default path.
No phase here should land without a concrete policy consumer exercising it — this is exactly the kind of surface that shouldn't ship ahead of something that uses it.
Path-based matching in `pkg/bpf/lsm` (`bpf_d_path` keyed on the kernel-resolved path) already defeats symlink/`/proc/self/root`-style indirection, and default-deny already closes the "copy a binary to an unlisted path" dodge (see #171). The gap neither closes: an attacker who overwrites the content at an already allow-listed path (e.g. replaces `/usr/bin/kubectl` in place) is still permitted, because the match is on path, not on what's actually in the file.
Recommended phasing
Phase 0 — platform gate
Add an `fs-verity`-support platform check alongside the existing BPF-LSM gate (`docs/users/platforms.md`). No enforcement change yet; this only tells us where the feature can ship at all.
Phase 1 — fs-verity digest matching, scoped narrow
Phase 2 — evaluate before going further
No phase here should land without a concrete policy consumer exercising it — this is exactly the kind of surface that shouldn't ship ahead of something that uses it.