4 Commits

Author SHA1 Message Date
leviathan 5b79b23ff2 ci: ASan/UBSan + clang-tidy lint + weekly drift check
Three new jobs in build.yml:

1. sanitizers (clang + ASan/UBSan)
   Runs the same 88-test suite under AddressSanitizer +
   UndefinedBehaviorSanitizer. -fno-sanitize-recover=all so any
   finding fails CI loudly rather than scrolling past. -O1 + frame-
   pointers preserved for usable backtraces. CC=clang because clang's
   sanitizer integration is more mature than gcc's; gcc-built binaries
   still get exercised by the matrix in the main 'build' job.

2. clang-tidy (advisory)
   Lints core/ + skeletonkey.c (the files we control most directly;
   module sources often bundle published PoC code we keep close to
   upstream style, so they're excluded). continue-on-error: true for
   now so it sets a baseline without blocking merges; we can tighten
   incrementally as the warning surface shrinks.

3. drift-check (cron + workflow_dispatch)
   Runs weekly (Mon 06:00 UTC) and on-demand. Two sub-steps:
     - tools/refresh-cve-metadata.py --check  (CISA KEV + NVD CWE)
     - tools/refresh-kernel-ranges.py         (Debian security tracker)
   Both already exit non-zero on actionable drift. Network-required,
   so NOT gated on regular PR runs — random PRs shouldn't fail because
   CISA published a new KEV entry. The job runs ONLY on schedule +
   manual trigger (if: github.event_name == 'schedule' || ...).
   When it fires, the GH Actions warning annotation points the
   maintainer at the right refresh script to rerun + commit.

Smoke-tested locally:
  - macOS local ASan+UBSan build: kernel_range tests pass; detect()
    tests skipped (non-Linux platform stubs).
  - clang-tidy not installed locally; CI installs from apt.
2026-05-23 20:46:27 -04:00
leviathan ea1744e6f0 tests: detect() unit harness with mocked ctx->host
Adds tests/test_detect.c — a standalone harness that constructs
synthetic struct skeletonkey_host fingerprints (vulnerable / patched /
specific-gate-closed) and asserts each migrated module's detect()
returns the expected verdict. First real test coverage for the corpus;
catches regressions in the host-fingerprint-consuming logic.

Initial coverage — 8 deterministic cases across the 4 modules that
already consume ctx->host:
- dirtydecrypt: 3 cases verifying 'kernel < 7.0 -> predates the bug'
  short-circuit on synthetic 6.12 / 6.14 / 6.8 hosts.
- fragnesia: unprivileged_userns_allowed=false -> PRECOND_FAIL.
- pack2theroot: is_debian_family=false -> PRECOND_FAIL.
- pack2theroot: has_dbus_system=false -> PRECOND_FAIL.
- overlayfs: distro=debian / distro=fedora -> 'not Ubuntu' -> OK.

Coverage grows automatically as more modules migrate to ctx->host
(task #12 below adds them). Each new module that consults the host
fingerprint can have its precondition gates tested with a one-line
EXPECT_DETECT call against a pre-built fingerprint.

Wiring:
- Makefile: new MODULE_OBJS var consolidates the module .o list so
  both the main binary and the test binary can share it without
  duplication. New TEST_BIN := skeletonkey-test target. 'make test'
  builds and runs the suite.
- .github/workflows/build.yml: install libglib2.0-dev + pkg-config so
  pack2theroot builds with GLib in CI (was previously stub-compiling).
  New 'tests — detect() unit suite' step runs 'make test' as a
  non-root user so modules' 'already root' gates don't short-circuit
  before the synthetic host checks fire.
- Test harness compiles cross-platform but assertions are #ifdef
  __linux__ guarded (on non-Linux all module detect() bodies stub-out
  to PRECOND_FAIL, making assertions tautological); macOS dev build
  reports 'skipped'.

Module change:
- pack2theroot p2tr_detect now consults ctx->host->is_root (with a
  geteuid() fallback when ctx->host is null) instead of calling
  geteuid() directly. Production behaviour is identical
  (host->is_root is populated from geteuid() at startup); tests can
  now construct non-root fingerprints regardless of the test
  process's actual euid. Exposed a real consistency issue worth
  fixing.

Verified in docker as non-root: 8/8 pass on Linux. macOS reports
'skipped' as designed.
2026-05-22 23:32:12 -04:00
leviathan 9593d90385 rename: IAMROOT → SKELETONKEY across the entire project
release / build (arm64) (push) Waiting to run
release / build (x86_64) (push) Waiting to run
release / release (push) Blocked by required conditions
Breaking change. Tool name, binary name, function/type names,
constant names, env vars, header guards, file paths, and GitHub
repo URL all rebrand IAMROOT → SKELETONKEY.

Changes:
  - All "IAMROOT" → "SKELETONKEY" (constants, env vars, enum
    values, docs, comments)
  - All "iamroot" → "skeletonkey" (functions, types, paths, CLI)
  - iamroot.c → skeletonkey.c
  - modules/*/iamroot_modules.{c,h} → modules/*/skeletonkey_modules.{c,h}
  - tools/iamroot-fleet-scan.sh → tools/skeletonkey-fleet-scan.sh
  - Binary "iamroot" → "skeletonkey"
  - GitHub URL KaraZajac/IAMROOT → KaraZajac/SKELETONKEY
  - .gitignore now expects build output named "skeletonkey"
  - /tmp/iamroot-* tmpfiles → /tmp/skeletonkey-*
  - Env vars IAMROOT_MODPROBE_PATH etc. → SKELETONKEY_*

New ASCII skeleton-key banner (horizontal key icon + ANSI Shadow
SKELETONKEY block letters) replaces the IAMROOT banner in
skeletonkey.c and README.md.

VERSION: 0.3.1 → 0.4.0 (breaking).

Build clean on Debian 6.12.86. `skeletonkey --version` → 0.4.0.
All 24 modules still register; no functional code changes — pure
rename + banner refresh.
2026-05-16 22:43:49 -04:00
leviathan 4943b82129 Phase 4 (partial): GitHub Actions build-check CI
- .github/workflows/build.yml: matrix of {gcc, clang} x {default,
  debug} builds on every push + PR. Smoke tests after build:
  --version, --list, --scan, --detect-rules auditd, --detect-rules
  sigma. Build failure breaks merge gate.
- Static-build job runs continue-on-error (glibc + NSS issue with
  static linking — getpwnam pulls in NSS at runtime; legacy DIRTYFAIL
  Makefile noted this. Revisit with musl-gcc to get a truly portable
  static binary).
- Kernel-VM matrix placeholder commented at the bottom of build.yml.
  Real kernel matrix needs self-hosted runners or a paid VM service —
  out of scope for tonight, in scope for Phase 4 followup.
2026-05-16 20:02:53 -04:00