{
  "finding_id": "DF-5011",
  "status": "reproduced",
  "verdict": "REPRODUCED (panic). sys/dev/misc/dimm/dimm.c:305-321 dimm_mod_unload() loops dimm_destroy() until the dimm_softc list is empty; since dimm_destroy() decrements a reference owned by a KPI user (dimm.c:184) and kfrees the softc at zero (dimm.c:195), module unload silently drains FOREIGN references and frees live objects. Demonstrated on the guest with a dep-less KPI user (mirroring in-tree ecc_e3.c, which omits MODULE_DEPEND on dimm): `kldunload dimm` returned 0, tore down hw.dimminfo and kfree()d the victims softc; the victims subsequent dimm_destroy() call faulted on the unmapped dimm.ko text (Fatal trap 12, fault VA = dimm.ko base 0xffffffff82600000 + 0x4a0) and the system died at the DDB prompt. A control module WITH MODULE_DEPEND(dimm,1,1,1) is fully protected (kldunload -> Device busy; auto-load of dimm.ko observed), isolating the defect to dimm.cs own unload path for dep-less users. Root-gated (kldunload) => severity Low; the same primitive is freed-object memory corruption (refcount dec + TAILQ_REMOVE + kfree of a live object) on ECC servers. fix.diff (refuse unload with EBUSY while any softc exists) validated in-guest: drain/free gone, correct lifecycle preserved.",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "exploit_chain": "root loads module-mode dimm.ko (kernel without `device dimm`; stock /boot/kernel/dimm.ko) -> dep-less KPI user (ecc_e3 pattern) calls dimm_create() and holds ref=1 -> root `kldunload dimm` -> linker has no dep ref -> MOD_UNLOAD -> dimm_mod_unload() drains the users ref (1->0), frees sysctl ctx, kfrees softc, unmaps dimm.ko -> victims next KPI call (dimm_destroy at detach, dimm_sensor_ecc_add on ECC interrupt) -> instruction fetch from unmapped module text / write to freed heap -> Fatal trap 12 -> panic, system down. Unprivileged trigger: none (no unprivileged entry point in dimm.c); ceiling is root-triggered panic/heap corruption.",
  "evidence": "run.log (baseline: kldunload dimm rc=0 with live ref, hw.dimminfo destroyed, then panic), panic.txt (Fatal trap 12, fault VA=0xffffffff826004a0 = dimm.ko+0x4a0, DDB), run.2.log (control with MODULE_DEPEND: Device busy, clean teardown), run.3.log (fix validated: veto + intact object + clean lifecycle), build.log, fix.diff (applies clean to sys/)",
  "kernel_refs": [
    "sys/dev/misc/dimm/dimm.c:305",
    "sys/dev/misc/dimm/dimm.c:316",
    "sys/dev/misc/dimm/dimm.c:184",
    "sys/dev/misc/dimm/dimm.c:195",
    "sys/dev/misc/ecc/ecc_e3.c:156",
    "sys/dev/misc/ecc/ecc_e3.c:387",
    "sys/kern/kern_linker.c:477"
  ],
  "poc_changes": "The orchestrator provided no seed PoC; authored from scratch. PoC module builds need: (1) module name baked in via sed (DECLARE_MODULEs internal ## pasting defeats macro renaming; CFLAGS+= in a kmod Makefile does not reach the compiler \u2014 the initial -DWANT_DEP build silently produced a dep-less control, which the first run exposed and which was rebuilt+verified via strings/MDT metadata); (2) compiling dimm.c itself as a kmod requires kernel-generated *_if.h copied from /usr/obj/usr/src/sys/X86_64_GENERIC into the kmod obj dir; (3) the bug path requires a kernel without `device dimm` (stock X86_64_GENERIC compiles dimm in, where MOD_UNLOAD never runs) \u2014 built in-guest with `make nativekernel` after commenting device dimm/ecc/memtemp.",
  "attempts": 3,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #1: Fri Sep 25 21:53:46 UTC 2026  root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64 (custom kernel w/o device dimm; stock baseline kernel: #0 Thu Jul 2 06:02:54 UTC 2026)",
  "runtime_sec": 1260,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df5011 && sh build.sh   (kernel precondition: make -j6 nativekernel KERNCONF=X86_64_GENERIC with device dimm/ecc/memtemp commented, then installkernel + reboot)",
  "run_cmd": "sh run.sh         (baseline, expects panic; run-control.sh and run-fix.sh are the control/fix scripts)",
  "code_hash": "8252a0fee7a27ff3d41db3f9222c287cbf9dacba6a09578780d032c6719cd75b",
  "notes": "Also verified live: MODULE_DEPEND fully protects declared dependents (dimm.ko auto-load observed) \u2014 the unprotected population is dep-less users, and in-tree ecc_e3.c is exactly that. Recommended companion fix: add MODULE_DEPEND(ecc_e3, dimm, 1, 1, 1) to sys/dev/misc/ecc/ecc_e3.c. dimm.c itself has no unprivileged attack surface (sysctl writes gated by SYSCAP_NOSYSCTL_WR, kern_sysctl.c:1446). Guest reset to clean `with-src` snapshot after the run (baseline panic + custom kernel reverted).",
  "recommended_fix": "dimm_mod_unload(): return EBUSY when any dimm_softc still exists (veto the module unload) instead of looping dimm_destroy() until the list is empty; propagate the error from MOD_UNLOAD (see fix.diff); optionally add the missing MODULE_DEPEND(ecc_e3, dimm, 1,1,1).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": false,
  "fix_verdict": "fix.diff (dimm_mod_unload -> int, EBUSY veto while list non-empty, error propagated from MOD_UNLOAD; forward prototype at dimm.c:75 updated too) built as dimm-fixed.ko in-guest and validated: with a dep-less user holding ref=1, `kldunload dimm-fixed` fails with Device busy and logs dimm0 is still referenced (ref 1); cannot unload; the softc and its sysctl tree survive; the user then destroys its own reference cleanly and the module unloads rc=0 afterwards. Baseline behavior (silent drain + kfree + victim panic) is gone. fix_patched_reproduced=false means the BUG does NOT reproduce on the patched module (the fix works), per the schema semantics.",
  "fix_evidence": "run.3.log (full fixed-module transcript), build.log (dimm-fixed.ko build), fix.diff (git apply --check passes against sys/)"
}