Files
shadow/docs/SECURITY-HARDENING.md
Pierre Warnier 42d701e25f docs: backfill CHANGELOG and SECURITY-HARDENING for review rounds
CHANGELOG [Unreleased]:
- Add Security section with review round 2 fixes (PAM zeroization,
  initgroups, SignalBlocker scoping, UmaskGuard !Send/!Sync, targeted
  newgrp hardening, atomic_write retry, crypt thread-safety docs,
  centralized hardening, println panic fix, unwind table suppression)
- Update 0.1.0 test count from 460+ to 580+, fuzz targets from 4 to 6

SECURITY-HARDENING.md:
- Add 7 implemented items from review round 2
2026-04-22 10:27:46 +02:00

2.5 KiB

Security Hardening Roadmap

Techniques adopted from OpenBSD and best practices for setuid-root tools.

Implemented

  • caller_is_root() uses getuid() not geteuid() for authorization
  • Atomic file writes with fsync + rename
  • Temp files created with 0o600 (no world-readable window)
  • Lock-via-hard-link (TOCTOU-resistant)
  • Stale lock detection only on ESRCH (not EPERM)
  • Password strings zeroed via zeroize crate
  • Absolute paths for subprocess execution (/usr/sbin/nscd)
  • PAM delegation (no custom password hashing)
  • TmpGuard drop pattern (no leaked temp files)
  • Signal blocking during file writes (#38 — SignalBlocker RAII)
  • Environment sanitization (#40 — sanitized_env() / harden_process())
  • Privilege drop during PAM conversation (#39 — PrivDrop RAII)
  • Core dump suppression (#43 — suppress_core_dumps())
  • Resource limit hardening (#44 — raise_file_size_limit())
  • Zero-length output guard (#45 — in atomic_write)
  • setuid(0) consolidation (#47 — before file operations)
  • Password input interrupt handling (#48 — custom SIGINT handler removed; signal blocking during file writes covers critical sections)
  • User enumeration prevention (#49 — early permission check for non-root callers)
  • O_CLOEXEC on file descriptors (#50)
  • Umask reset (#51 — UmaskGuard RAII)
  • Landlock filesystem restriction (#41 — apply_landlock() in passwd)
  • PAM password buffer zeroization (immediate zeroize after use)
  • initgroups() in newgrp (prevent supplementary group leak across exec)
  • UmaskGuard !Send/!Sync (PhantomData<Rc<()>> — prevent cross-thread umask corruption)
  • atomic_write retry on stale temp file from prior crash
  • SignalBlocker scoped to critical sections only (dropped before long-running ops)
  • Centralized hardening in shadow_core::hardening (deduplicated across tools)
  • Targeted hardening in newgrp (no RLIMIT_FSIZE leak to exec'd shell)

Not Yet Implemented

Seccomp-BPF

Restrict syscalls to only what passwd needs after initialization. Complex but effective — sudo-rs uses this approach.

References