Add signed-package verification and anti-rootkit cross-view (v0.7)

Closes the tamper-evidence loop with two trust anchors the attacker can't
forge from userland:

- pkgdb Layer 2: verify on-disk files against the .MTREE in the *signed*
  cache package, surviving a rewritten local checksum DB. Rotating-sample
  cadence keeps it affordable; flags pkg_signature_mismatch (sid 100027)
  and SigLevel downgrades (sid 100026). Fixes parse_mtree, which required
  type=file on every line and so matched nothing on real pacman MTREEs
  (which use a /set type=file default with bare file entries).
- rootcheck: anti-rootkit cross-view — hidden processes, modules, ports,
  and promiscuous interfaces, each caught by diffing two views of the
  same state (sids 100022-100025).

Wired both through config, the daemon (off-loop slow cadence), and CLI
(pkgdb-verify, rootcheck). 14 new tests (95 total). Docs + version bump.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-06-01 05:42:57 -07:00
parent 34bc09041a
commit 1de5e86fed
10 changed files with 766 additions and 5 deletions

View file

@ -71,6 +71,17 @@ class Config:
pkgdb_verify: bool = True # detect out-of-band package-DB edits
pkgdb_interval: int = 600 # seconds between DB integrity checks
heartbeat_max_age: int = 120 # heartbeat older than this = stale
# Layer 2 — verify on-disk files against the signed cache package (survives
# a rewritten checksum DB). Expensive, so it samples a rotating slice of
# packages each pass; off by default (needs the package cache populated).
pkgdb_pkgverify: bool = False
pkgdb_pkgverify_interval: int = 21600 # seconds between Layer-2 passes
pkgdb_pkgverify_sample: int = 40 # packages verified per pass (rotates)
# anti-rootkit (cross-view: ask the same question two ways, compare)
rootcheck_enabled: bool = True
rootcheck_interval: int = 300 # seconds between cross-view sweeps
rootcheck_pid_cap: int = 65536 # upper PID to brute-force via kill(0)
# eBPF on-ramp
capture_execve_bpftrace: bool = False