{
  "finding_id": "DF-2915",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "REPRODUCED, both as root-cause and end-to-end. sleepq_lock() (sys/kern/subr_sleepqueue.c:208-209) assumes objcache_get() returns zeroed sleepqueue_wchan objects, but sleepq_wc_cache is an objcache_create_simple() cache whose allocator objcache_malloc_alloc() (kern_objcache.c:571-577) kmalloc()s without M_ZERO and registers no ctor (kern_objcache.c:386-391). On the stock kernel a probe that pollutes the M_SLEEPQ zone with 0xAA and rebuilds the identical cache saw 256/256 objcache_get() objects violating the KKASSERT precondition (uninitialized wc_wchan/wc_refs/wc_blocked). End-to-end: on a kernel with only the known DF-0139 hash bug masked (test-only precondition; without it sleepq_lock GPFs in 'lock xaddl %edx,sleepq_chains(%r13)' first - captured in panic_df0139_stockkernel.txt), the first real sleepq_lock/sleepq_add/sleepq_wait sequence panics with 'assertion \"wc->wc_wchan == NULL && wc->wc_refs == 0\" failed in sleepq_lock at subr_sleepqueue.c:209' (panic.txt). On production (non-INVARIANTS) kernels the KKASSERT is compiled out and the garbage wc (wc_wchan != NULL) enters sc_wchead where it can never match a wchan nor serve as a free slot, so the for(;;) re-search loop allocates again - unbounded M_SLEEPQ growth/livelock plus permanently stuck entries and inflated sc_free_count. Fix validated: with fix.diff (bzero after objcache_get) the identical trigger runs clean through lock/add/wait/broadcast on the rebuilt kernel. Reachability: the file is compiled into every kernel (sys/conf/files:1453) but has ZERO in-tree callers; it exists for FreeBSD-compat/Linux-KPI kld modules, so triggering requires loading a consumer module (root-only). No unprivileged path; no privesc chain exists for this bug class.",
  "exploit_chain": "",
  "evidence": [
    "run.log - stock-kernel probe: 'SQDEMO probe: 256/256 objcache_get() objects violate the KKASSERT precondition at subr_sleepqueue.c:209'",
    "panic.txt - end-to-end on mask-only kernel #1: panic assertion wc->wc_wchan == NULL && wc->wc_refs == 0 at subr_sleepqueue.c:209, backtrace sleepq_lock+0x200 <- sq_sleeper+0x10",
    "panic_df0139_stockkernel.txt - stock kernel: Fatal trap 9 GPF at sleepq_lock+0x54 'lock xaddl %edx,sleepq_chains(%r13)' re-demonstrating why DF-0139 must be masked to reach the DF-2915 path",
    "../DF-2917/run.log - kernel #2 (mask+fix2915): same kldload + 0xAA pollution, kldload-rc=0, NO panic, module completes - fix validated",
    "VERDICT.md - full narrative incl. production-kernel (non-INVARIANTS) manifestation analysis"
  ],
  "kernel_refs": [
    "sys/kern/subr_sleepqueue.c:145",
    "sys/kern/subr_sleepqueue.c:185",
    "sys/kern/subr_sleepqueue.c:208",
    "sys/kern/subr_sleepqueue.c:209",
    "sys/kern/subr_sleepqueue.c:212",
    "sys/kern/kern_objcache.c:378",
    "sys/kern/kern_objcache.c:386",
    "sys/kern/kern_objcache.c:571",
    "sys/kern/kern_objcache.c:582"
  ],
  "poc_changes": "Authored from scratch (no seed PoC - new pass-2 finding). Key hurdles: (1) DF-0139's wild hash index panics spin_lock() before the DF-2915 path is reachable, so a TEST-ONLY mask patch (test_df0139_mask.diff) was applied in the guest's /usr/src; (2) 'make nativekernel' builds but does NOT install - 'make installkernel' is required or the box keeps booting the old kernel; (3) kmod build details: kthread_create needs <sys/kthread.h>, sbticks is already declared in <sys/kernel.h> (redeclaring trips -Werror=redundant-decls); (4) M_SLEEPQ is 'struct malloc_type M_SLEEPQ[1]' so modules must extern it as an array; (5) module .ko lands in the obj dir (/usr/obj/tmp/...) and /tmp is wiped on reboot - copy to /root.",
  "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": 2820,
  "guest_dirty": 0,
  "build_cmd": "sh /root/sqdemo/build.sh   (modules) ; cd /usr/src && make -j6 nativekernel KERNCONF=X86_64_GENERIC && make installkernel KERNCONF=X86_64_GENERIC   (test kernels)",
  "run_cmd": "kldload /usr/obj/tmp/sqdemo/sqprobe/sqprobe.ko   (probe, stock) ; kldload /root/sqe2e.ko   (e2e trigger)",
  "code_hash": "9fa6c75f5ee70aa5f6a44b564f087fe8b4bbab8fcb52b41c45aa0a0ef5f47f89",
  "notes": "Code hash is sha256 of sqe2e.c (primary trigger); sqprobe.c = 61639636bd8cf8079ed757c071b96843d1bcf34a382c89d0ab1f5e4c03d8fbf6. Kernel sequence: stock #0 (Jul 2) -> #1 Sep 3 09:02:18 (DF-0139 mask only: PANIC at :209) -> #2 Sep 3 09:16:39 labelled '#1' (mask+DF-2915 fix: clean) -> #3 Sep 3 09:26:13 labelled '#2' (mask+2915+2917 fixes: clean, real sleeping). kbuild2_fix2915.log holds the full untrimmed fix-kernel build. Production-kernel (non-INVARIANTS) garbage-chain/alloc-loop manifestation is source-derived; executing it would need a non-INVARIANTS build (out of scope, mechanism fully determined).",
  "recommended_fix": "Zero the freshly allocated wc in sleepq_lock(): replace the KKASSERT at subr_sleepqueue.c:209 with bzero(wc, sizeof(*wc)) (or create sleepq_wc_cache with a zeroing allocator/ctor).",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Thu Sep  3 09:16:39 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (bzero(wc, sizeof(*wc)) replacing the load-bearing KKASSERT) applied to the guest /usr/src tree on top of the DF-0139 test mask; kernel rebuilt (kbuild2_fix2915.log, rc=0) and installed. The exact trigger that panicked the baseline kernel (same sqe2e.ko, same 0xAA pollution of M_SLEEPQ, same first-use sleepq_lock) loads and completes the full lock/add/wait/broadcast sequence with no panic and the guest stays up. fix_status: fixed.",
  "fix_evidence": "kbuild2_fix2915.log (full build log); ../DF-2917/run.log lines: 'kldload-rc=0', 'SQDEMO e2e: M_SLEEPQ polluted with 0xAA...' followed by completed round trips on the fixed kernel; panic.txt shows the same trigger on the unfixed kernel."
}
