β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2858

shmfork() bcopy's transient shmmap_s reservation state: fork landing in shmat's blocked window permanently burns a SHMSEG slot in the child (and gives it an un-accounted, un-shmdt-able mapping)

Field Value
ID DF-2858
Status new
Severity Low
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L
CWE CWE-362 (resource leak)
File sys/kern/sysv_shm.c
Lines 646-663 (reservation site :306-318)
Area kern
Confidence likely
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket base:kern
Reported pending
Known CVE none
CVE match novel

Summary

sys_shmat marks a shmmap_s slot reserved=1 for the duration of its blocking vm_map_find window; shmfork bcopy's the ENTIRE array including that transient state. The child's copy of reserved=1/shmid=βˆ’1 can never be cleared (only the parent's in-flight shmat clears its own array), permanently shrinking the child's usable shmseg slots by one per hit; if the fork lands after vm_map_find inserted the entry, the child's copied vm_map holds the mapping while its vm_shm entry stays shmid=βˆ’1 β€” shmdt/exit skip it (refcounting still balances via the map teardown, so a leak, not corruption). Unpriv fork-vs-shmat racing; per-process slot exhaustion + loss of SysV accounting. Fix: un-reserve inherited slots when copying in shmfork.

Timeline

  • 2026-09-02 Discovered during pass-2 audit of sysv_shm.c (GLM 5.3).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2858 Β· 5 files
FileTypeDescriptionSize
shmfork_race2.c β€” 3.0 KB view raw
shmfork_race.c (v1, detector artifact - kept for the record) β€” 2.9 KB ↓ download
run.log β€” 1.1 KB view raw
v1_detector_artifact.log β€” 385 B view raw
fix.diff β€” 793 B view raw

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

Fix (clear inherited reserved flags in shmfork) compile- and boot-validated; with the corrected detector the patched kernel shows the same zero-burn behavior as the stock kernel (the race itself was not reproducible, so no differential A/B exists).

df2858_final.log: 0 burns on patched kernel (3000 forks)
↓ fix.diffper-fix-DF-2858

Confirmed kernel references

Detail

Exploit chain

(intended) fork inside sys_shmat reservation window -> child inherits reserved=1/shmid=-1 -> permanently unusable slot - NOT OBSERVED in 10,000 forks with corrected detector

Evidence (decisive lines)

shmfork_race2.c (corrected detector); df2858_final.log: 0 burns stock (3000 + 4000 under pressure), 0 burns patched (3000)

PoC changes

v1 detector miscounted normal single-attachment inheritance as slot loss; v2 adds fixed-address attach + mincore inheritance probe

Verified recommended fix

--- sys/kern/sysv_shm.c 2026-06-29 12:51:19.000000000 +0000

Verdict

DOWNGRADED to not_reproduced after the PoCs own detector was proven wrong - an important negative result. The code gap is real and line-accurate: sys_shmat marks a shmmap_s slot reserved=1 across its blocking window (sys/kern/sysv_shm.c:312-322), shmfork bcopys the entire array including that transient state (:656), and nothing ever clears the childs copy; the original PoC appeared to reproduce at a 90% rate (3622/4000 children at reduced capacity) but that detector counted capacity < shmseg as slot loss while the parents attacher thread legitimately holds one attachment at fork time. A corrected detector (parent attaches at a FIXED address; child counts capacity AND probes whether the fixed address is mapped; burn = reduced capacity with NO inherited mapping) produced ZERO burns in 10,000 forks on the stock kernel, with and without memory pressure (which would widen the vm_map_find window). The shm_token serialization evidently keeps forks out of the reservation window under tested conditions. The fix (clear inherited reserved flags in shmfork) is correct, compile- and boot-validated, and the patched kernel shows the same zero-burn behavior with no regression.