{
  "finding_id": "DF-5065",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Reproduced 1/1 deterministic (no race, no timing): on a fresh with-src guest, seven sequential steps -- kldload dm; create tableless device; kldunload dm (EBUSY veto, kern_linker.c:518 refs-- 1->0); remove device; kldload dm_target_linear (dep ref 0->1, MODULE_DEPEND pin permanently defeated); kldunload dm (SUCCEEDS: dm_target_uninit at dm_target.c:284-287 frees linears registered dm_target_t and lockuninits the registry, dm.ko text freed); kldunload dm_target_linear -- executes dm_target_remove() through freed dm.ko text: Fatal trap 12, IP=0xffffffff82604950 (supervisor read instruction, page not present; dm.ko was mapped at 0xffffffff82600000), guest down at db>. Root cause is in-file: dm_target_uninit performs no ref_cnt/registry validation at all (contrast dm_target_removes EBUSY at dm_target.c:181) and its caller dmdestroy() ignores its return. Race variant: an ioctl holding a looked-up target ref (dm_ioctl.c:737) when MOD_UNLOAD slips past the counter check gets a freed heap dm_target_t used by dm_table_destroy (dm_table.c:150-157) -- same missing-validation defect, not separately demonstrable from DF-4751s crash sites. Trigger needs root (kldload/kldunload, securelevel<=0); ioctl side is operator-group reachable.",
  "exploit_chain": "kldload dm -> create device (counter=1) -> kldunload dm (EBUSY veto; linker veto-path refs-- destroys dm.kos base ref) -> remove device (counter=0) -> kldload dm_target_linear (dep ref on underflowed dm) -> kldunload dm (full unload: registry freed with linears entry in it, dm.ko freed) -> kldunload dm_target_linear -> call into freed dm.ko text -> Fatal trap 12. Escalation ceiling: freed-kernel-text execution primitive groomed by root against root; treated as deterministic-panic + memcorrupt-class correctness bug (Medium).",
  "evidence": "panic.txt (Fatal trap 12, IP in freed dm.ko text, Device Mapper unloaded printed with linear loaded); run.log (chain narration); run_patched.log (identical PoC on fix.diff: kldunload dm vetoed Device busy, linear unloads cleanly, guest STILL_UP); fix.diff (dm_target.c + device-mapper.c, -Werror clean module build); VERDICT.md (full line-by-line trace + fix-validation narrative)",
  "kernel_refs": [
    "sys/dev/disk/dm/dm_target.c:277",
    "sys/dev/disk/dm/dm_target.c:284",
    "sys/dev/disk/dm/dm_target.c:287",
    "sys/dev/disk/dm/dm_target.c:292",
    "sys/dev/disk/dm/device-mapper.c:161",
    "sys/dev/disk/dm/device-mapper.c:187",
    "sys/dev/disk/dm/device-mapper.c:194",
    "sys/dev/disk/dm/dm_target_error.c:73",
    "sys/kern/kern_linker.c:494",
    "sys/kern/kern_linker.c:514",
    "sys/kern/kern_linker.c:518"
  ],
  "poc_changes": "Harness is a de-threaded adaptation of the DF-4751 proplib client (create/remove only); the deterministic chain replaced DF-4751s churn/race with seven sequential shell steps; fix.diff regenerated mechanically after hand-written hunk counts failed patch --dry-run.",
  "attempts": 2,
  "guest_uname": "DragonFly dfbsd 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": 900,
  "guest_dirty": 0,
  "build_cmd": "guest: cc -O2 -Wall -I/tmp/propinc -o /tmp/dmt_registry_uaf dmt_registry_uaf.c -lprop ; fix: cd /usr/src/sys/dev/disk/dm && make obj && make && cp /usr/obj/usr/src/sys/dev/disk/dm/dm.ko /boot/kernel/dm.ko",
  "run_cmd": "vm.sh reset with-src; sh build.sh; vm.sh run_root sh /tmp/run.sh",
  "code_hash": "6a38de60eac89db619c1f87fd88c9b9a5e4614be8c3c6021d4ea32ba6bfaf82a",
  "notes": "Deterministic chain is enabled by the kern_linker.c:518 veto-path refs-- (an accounting bug in its own right, out of this findings file -- recommend pass-2 audit of kern_linker.c); the dm-side fix stands alone and was proven to kill the chain with the linker bug still present. Relationship to known findings: NOT a dupe of DF-4751 (different file, different defect -- the missing second veto -- and the deterministic variant needs no race) nor of DF-2437 (delay ignoring remove()s EBUSY; here the EBUSY machinery itself is absent). Guest reset with-src performed after both runs.",
  "recommended_fix": "dm_target_uninit: return EBUSY when the registry is non-empty (any registered or referenced target) instead of freeing everything + lockuninit; dmdestroy: unregister builtin error/zero targets explicitly before the check and propagate uninits error so MOD_UNLOAD vetoes.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (dm_target.c non-empty-registry EBUSY + device-mapper.c explicit builtin unregistration and error propagation; both files ship in dm.ko) applied to a fresh with-src guest, module rebuilt -Werror-clean, installed; the IDENTICAL PoC no longer panics: the fatal kldunload dm is vetoed with Device busy while dm_target_linear is registered, linear then unloads cleanly through live dm text, and the dependency cascade unloads dm.ko correctly afterwards (STILL_UP). Normal dm unload still works (demonstrated by the clean cascade at end of patched run).",
  "fix_evidence": "run_patched.log (full trace: veto at step 5, clean unload at step 6, STILL_UP); fix.diff; VERDICT.md fix-validation section"
}