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

plimit COW swap stores p->p_limit without p->p_spin, leaving a theoretical ref-acquisition race window against cross-process readers (schedcpu)

Field Value
ID DF-2913
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:L
CWE CWE-667 Improper Locking
File sys/kern/kern_plimit.c
Lines 189, 226 (readers :100-103, kern_descrip.c:624-632)
Area kern
Confidence speculative
Discovered 2026-09-02
Pass 2 (GLM 5.3 second pass)
Bucket memcorrupt
Reported pending
Known CVE none
CVE match novel

Summary

readplimits reads p->p_limit and takes a reference while holding p->p_spin shared, but the writers of p->p_limit — the COW swap in plimit_modify (:226) and plimit_lwp_fork (:189) — store the new pointer with no lock at all. The shared spinlock therefore does not serialize readers against the writer; it only serializes readers against each other. For user threads this is saved by the EXCLUSIVE invariant (a multithreaded process never swaps; a single-threaded process has no concurrent reader), but schedcpu's cross-process check (kern_synch.c:308 → plimit_testcpulimit → readplimits) can race a single-threaded target's setrlimit/lwp_create COW swap: the kernel thread loads the old p->p_limit under the spinlock and then increments p_refcnt in a separate locked instruction (confirmed in the shipped kernel at 0xffffffff80655b5c→0xffffffff80655b60). If every remaining reference drained inside that 2-instruction window, the increment would land on freed memory → later UAF decrement. Not reachable with any reliability (preemption must land exactly between two instructions AND a multi-millisecond teardown must complete inside it) — Info/speculative hardening so the lock protocol matches its documented intent. The related CPU-limit kill-test overflow candidate was FALSIFIED live on the guest (unsigned predicate confirmed in disassembly; SIGXCPU + survival delivered correctly; evidence findings/poc/DF-2913/). plimit_testcpulimit's comment also claims a spinlock retest that does not exist — benign on x86_64.

spin_lock(&p->p_spin) around both COW pointer stores (leaf lock, no inversion risk); optionally implement or delete the stale :456-459 comment.

Timeline

  • 2026-09-02 Discovered during pass-2 audit of kern_plimit.c (GLM 5.3); overflow candidate falsified live, invariant protocol proven sound.

Discussion (0)

No comments yet.