Prevent SHM SIGBUS on full backing stores

Merged
KT
3mo ago
+1792-36

Summary

  • allocate the complete Linux SHM backing file with native fallocate() before mapping it
  • return an explicit allocation-stage error in C, Rust, and Go instead of risking SIGBUS during zero-fill
  • preserve baseline transport fallback for managed services when SHM allocation fails
  • add deterministic fault coverage and a required real size-limited tmpfs regression
  • document Linux allocation and Windows committed-mapping behavior

Safety and compatibility

  • no wire layout, offsets, capacities, negotiation values, or Windows transport code changed
  • unsupported Linux filesystems or ordinary seccomp errno denials disable SHM for the session; no sparse fallback weakens the safety guarantee
  • native Windows and MSYSTEM=MSYS continue to use page-file-backed committed mappings
  • the C error enum is appended; Rust adds ShmError::Allocate(i32); Go adds ErrShmAllocate with the OS cause wrapped

Validation

  • Linux CTest: 49/49
  • C coverage: 91.8% total; SHM source 91.1%
  • Rust: 380/380 tests; 92.63% total coverage; SHM source 96.35%
  • Go: 90.2% total coverage; Linux SHM source 91.9%
  • ASAN/UBSAN: 7/7; TSAN: 6/6
  • real 64 KiB tmpfs exhaustion: C, Rust, and Go return ENOSPC normally, emit no READY marker, receive no signal, and leak no file
  • Alpine 3.24.1 / musl 1.2.6 independently passes the C and real-tmpfs regression
  • native Windows/MSYS functional, service, cache, stress, and C/Rust/Go interoperability validation passed; Windows SHM passed 10 consecutive runs
  • all 11 paired MinGW/MSYS benchmark policy rows passed
  • static analysis, dependency/security audits, formatting, and shell/workflow validation passed locally

Tracking

SOW: .agents/sow/current/SOW-0030-20260712-shm-sigbus-on-full-backing-store.md


Summary by cubic

Preallocate Linux SHM regions with native fallocate() and return explicit allocation errors to prevent SIGBUS when /dev/shm or the backing filesystem is full. Keeps services running by falling back to baseline and adds a real tmpfs regression and deterministic fault tests across C, Rust, and Go.

  • Bug Fixes

    • Allocate with fallocate() before mmap; keep zero-fill; remove sparse ftruncate creation; retry EINTR.
    • Return explicit errors on allocation failure: C NIPC_SHM_ERR_ALLOCATE, Rust ShmError::Allocate(i32), Go ErrShmAllocate (wraps OS error); clean up and preserve errno.
    • Maintain managed fallback: SHM is dropped for the session and baseline is used when available; no wire/layout changes; Windows/MSYS unchanged.
    • Add required regression: real size-limited tmpfs test (test_shm_full_backing_store) and allocation fault injection; CI job “SHM Full Backing Store” now resolves ctest from the configured CMake toolchain for portability; docs updated.
  • Migration

    • Ensure Linux seccomp profiles allow fallocate; errno-returning denials disable SHM for the session, while kill/trap actions cannot be auto‑handled.
    • No other changes needed; Windows and MSYS behavior is unchanged.
    • Re-vendoring into netdata/netdata will follow after merge.