{
  "finding_id": "DF-2677",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "sys_shmat() (sys/kern/sysv_shm.c) counts the attach (shmseg->shm_nattch++) only at the very end of the syscall, after several operations that can block (vm_object_hold at :1025, vm_map_find at :1027); LWKT drops shm_token across blocking points, so a concurrent shmctl(IPC_RMID) (:443-446) sees shm_nattch==0 and calls shm_deallocate_segment() -> vm_object_deallocate() -> vm_object_terminate(), which then finds a live reference and panics unconditionally: 'panic: vm_object_terminate2: object with references, ref_count=1'. Reproduced twice on the stock kernel (traces via sys_shmdt and sys_shmctl) with an unprivileged trigger (creator+faulter processes), reliably within ~100s when kern.ipc.shm_use_phys>=2 (root-set documented tunable whose prealloc loop holds the object token and hugely widens shmat's blocking window); ~5 minutes of racing at the default (=1) did not reproduce, so default-config reachability is likely-but-unproven. Unobserved interleavings (RMID between shmat's reference and its nattch++ in the stock kernel) free the segment under a live mapping, leading to stale decrements on a recycled shmseg (bounded fixed-offset int corruption) - not demonstrated. An attempted minimal fix (count the attach before the first blocking op, unwind on vm_map_find failure) demonstrably reduced but did not close the race: the same panic reproduced on the patched kernel (panic_postfix.txt); since every vm_map-side reference implies a counted attach, the residual reference comes from an uncounted vm_object_reference path not serialized by shm_token (not pinned within budget). Upstream-grade fix requires reworking segment teardown synchronization (all attach-accounting sites before any blocking op - shmat AND shmfork's kmalloc - or refcount-driven teardown).",
  "exploit_chain": "unprivileged users: P1 loops shmget(8MB, IPC_CREAT|IPC_EXCL) + IPC_RMID; P2..P17 (16 faulters) discover each segment via shmget(key,0,0), shmat() and write-fault all pages. The fault load contends the object token so P2's shmat blocks inside vm_object_hold() with shm_token dropped; P1's IPC_RMID slips into that window, reads shm_nattch==0, and terminates the object that the in-flight shmat then references -> vm_object_terminate2 panic (kernel DoS; guest dies at ddb).",
  "evidence": [
    "panic.txt: two stock-kernel captures with full traces (shm_deallocate_segment <- vm_object_deallocate <- vm_object_terminate, via sys_shmdt and sys_shmctl) + race-window source annotation",
    "shm_rmid_race.c: unprivileged PoC (creator + N faulter processes)",
    "panic_postfix.txt: same panic on the patched kernel - first fix attempt incomplete",
    "fix.diff: attempted fix (early nattch++ with failure-path unwind)"
  ],
  "kernel_refs": [
    "sys/kern/sysv_shm.c:361",
    "sys/kern/sysv_shm.c:1023",
    "sys/kern/sysv_shm.c:1025",
    "sys/kern/sysv_shm.c:1027",
    "sys/kern/sysv_shm.c:1055",
    "sys/kern/sysv_shm.c:443",
    "sys/kern/sysv_shm.c:444",
    "sys/vm/vm_object.c:853"
  ],
  "poc_changes": "PoC written fresh during verification (discovered while chasing DF-2676's reachability). v1 (embedded in ../DF-2676/shm_grab_race.c) reproduced the panic immediately at shm_use_phys=2; factored out into shm_rmid_race.c with faulter-count argv; default-config variant raced ~5min without reproduction (recorded honestly).",
  "attempts": 4,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "runtime_sec": 1980,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o shm_rmid_race shm_rmid_race.c",
  "run_cmd": "sysctl kern.ipc.shm_use_phys=2 && su -m nobody -c ./shm_rmid_race 30000 16",
  "code_hash": "ac78b7f74fd3ef1bdf4dad4821783412452395376e7b5d630607094e943bc7ca",
  "notes": "Severity Medium: unprivileged local kernel panic, reliable under a documented non-default tunable (kern.ipc.shm_use_phys>=2 - the database-host setting), racy at default config. Panic check is unconditional (not INVARIANTS-gated). Same-bug-shape secondary effects (recycled-shmseg accounting corruption) are code-derived but unobserved.",
  "recommended_fix": "Count the attach (shmseg->shm_nattch++) before the first potentially-blocking operation in sys_shmat, mirror-decrement on vm_map_find failure (done in fix.diff), AND audit the remaining attach-accounting sites (shmfork's M_WAITOK kmalloc before its nattch++ loop) or move segment teardown to refcount-driven destruction; the minimal patch alone was proven insufficient on the guest.",
  "fix_status": "fix_failed",
  "fix_kernel_uname": "DragonFly 6.5-DEVELOPMENT #1: Sun Aug 30 13:38:49 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 1,
  "fix_verdict": "INCOMPLETE: with fix.diff applied (early nattch++ + failure-path unwind; kernel #1 13:38:49, symbol shift confirms new code), the identical PoC still panics with vm_object_terminate2 ref_count=1 via sys_shmctl within 120s (panic_postfix.txt). The shmat-side window is closed but at least one other uncounted reference path survives; full fix needs the teardown-synchronization rework described in recommended_fix.",
  "fix_evidence": [
    "panic_postfix.txt",
    "fix.diff"
  ]
}
