{
  "finding_id": "DF-4472",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Uninitialized stack pointer `type` (never initialized at dm_ioctl.c:684/690-695; prop_dictionary_get_cstring_nocopy at :731 leaves it untouched when the \"type\" key is absent) is dereferenced as a C string by dm_target_lookup (strcmp, dm_target.c:127) and dm_target_autoload (ksnprintf, dm_target.c:74). Verified three ways on the guest: (1) groom mode proves the wild lookup executed on 250/250 rounds (typeless reload returns the :741 ENOENT and wipes the inactive table destroyed at :722-723 -- the only ENOENT return after that point); (2) console printed the garbage string via the autoload ksnprintf; (3) flood mode produced a fatal trap 12 page fault at strcmp+0xc (fault VA 0x8) and killed the guest. Ceiling is a reliable local DoS (panic) for an operator-group user -- wild read, no write primitive, so no escalation chain (hard blocker). Fix (type=NULL init + checked get_cstring_nocopy -> EINVAL) validated on a rebuilt dm.ko: groom returns EINVAL, flood survives 8x800 with no panic.",
  "exploit_chain": "",
  "evidence": "run.log (groom 50/50 + 200/200 destroy-proof; flood -> panic; patched: rv2=22, no panic); panic.txt (Fatal trap 12, Stopped at strcmp+0xc: movzbl (%rdi,%rax,1),%edx; dm: could not autoload module for target <garbage>); fix.diff + fix validation section of run.log",
  "kernel_refs": [
    "sys/dev/disk/dm/dm_ioctl.c:684",
    "sys/dev/disk/dm/dm_ioctl.c:690-695",
    "sys/dev/disk/dm/dm_ioctl.c:730-732",
    "sys/dev/disk/dm/dm_ioctl.c:737-741",
    "sys/dev/disk/dm/dm_target.c:127",
    "sys/dev/disk/dm/dm_target.c:74",
    "sys/libprop/prop_dictionary_util.c:185-198"
  ],
  "poc_changes": "Authored fresh (pass-2 finding, no seed). Two modes: groom (valid reload then typeless reload + inactive-table query via table ioctl with DM_QUERY_INACTIVE_TABLE_FLAG) and flood (multi-threaded malformed reloads with padding entries to vary stack residue). Added pre-round verification that reload#1 actually loaded (defends against the trivial empty-table explanation).",
  "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": 2100,
  "guest_dirty": 0,
  "build_cmd": "cc -o dm_uninit_type dm_uninit_type.c -lprop -lpthread",
  "run_cmd": "./dm_uninit_type 200 ; ./dm_uninit_type --flood 8 800",
  "code_hash": "8ec0e07cab4afb394ad46ffd75c646e3431612c932feab9b5a4e83c64939b4cf",
  "notes": "Same trigger surface as the known DF-1639/DF-2448 family (missing proplist members) but a distinct defect: those are NULL-pointer derefs of cmd_data/iterator; this is an uninitialized stack POINTER VALUE used as a string. Threat model: /dev/mapper/control is 0640 root:operator (device-mapper.c:181) -- operator-group member or root required.",
  "recommended_fix": "Initialize type=NULL before the loop and per iteration; reject entries whose DM_TABLE_TYPE is missing/not a string with EINVAL instead of looking up the stale pointer.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Baseline: groom proved the wild read on 250/250 rounds and flood panicked the guest (trap 12, strcmp+0xc). Patched (dm.ko rebuilt from fix.diff, -Werror clean, kldload-ed): groom returns EINVAL(22) every round (type checked before lookup), flood 8 threads x 800 completes with no panic, guest healthy.",
  "fix_evidence": "run.log fix-validation section; fix.diff (combined dm_ioctl.c diff, hunk adding type=NULL + checked prop_dictionary_get_cstring_nocopy)"
}