{
  "finding_id": "DF-2237",
  "status": "reproduced",
  "reproduced": 1,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Verified on stock DFly 6.5-DEVELOPMENT guest: iconv_xlat16_conv line 192 dereferences d_table[c1] without a NULL recheck after case conversion mutates c1/c2 at lines 155-158 (double-byte towlower via armed _wctype pair, fault VA 0xc) and lines 186-189 (single-byte XLAT16_HAS_FROM_LOWER_CASE flag path, fault VA 0x108). Both faults are supervisor READs of NULL plus a 0..0x1fc table-chosen offset. Tables were armed via the real kern.iconv.add sysctl byte format and the conv driven through the exported iconv KPI that msdosfs uses per filename char. Fix guard validated A/B: controls bit-identical, both triggers degrade to ret=-1, no panic.",
  "exploit_chain": "",
  "evidence": "panic.txt and t1_boot.log:210 (Fatal trap 12, fault VA 0x108, supervisor read, stopped at iconv_xlat16_conv+0x259 movl (%rdi,%rdx,1),%edi); panic2.txt and t2_boot.log:208 (fault VA 0xc); fix_run.log / fix_dmesg.txt (controls 41 42 / 63 / 12 34 identical pre and post fix, triggers SURVIVED ret=-1); fix.diff (guard before line 192); mmap0_user.log (unpriv user can map page 0 - read hits attacker-owned page, all code sinks are bounded <= 3-byte conversion outputs, so no escalation)",
  "kernel_refs": [
    "sys/libiconv/iconv_xlat16.c:155-158",
    "sys/libiconv/iconv_xlat16.c:186-189",
    "sys/libiconv/iconv_xlat16.c:192",
    "sys/libiconv/iconv_xlat16.c:142",
    "sys/libiconv/iconv_xlat16.c:163",
    "sys/libiconv/iconv.c:397-443",
    "sys/vfs/msdosfs/msdosfs_conv.c:903",
    "sys/vfs/msdosfs/msdosfs_conv.c:988",
    "lib/libkiconv/xlat16_iconv.c:258-266"
  ],
  "poc_changes": "authored from scratch (no seed pack): armtbl.c registers 3 crafted sparse xlat16 pairs via the real sysctl wire format; df2237_mod.c KLD harness drives the real exported iconv KPI in 3 compile-time modes; KCFLAGS required because sys/conf/kmod.mk:98 resets CFLAGS; first fix-validation attempt hit a stale /usr/obj module picked by find|head -1 plus a Hammer2 rollback after a DDB kill - redone with explicit paths, syncs and hash verification",
  "attempts": 3,
  "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": 2700,
  "guest_dirty": 0,
  "build_cmd": "sh /root/df2237/build.sh",
  "run_cmd": "kldload /boot/kernel/libiconv.ko && /root/df2237/armtbl && kldload /usr/obj/root/df2237/km1/df2237_1.ko",
  "code_hash": "75fa8d8e60b3b31920aab3015eb48828d31188dbddbe7d112b1b5126362b5891",
  "notes": "Root-armed local DoS / latent-KPI robustness bug: kern.iconv.add and mounting need root, after which any user walking an msdosfs mount with -C reaches the path per lookup. Real builder only self-triggers on locale/charset divergence (locale tolower targets vs iconv occupancy are independent sources; no _wctype pair is registered at all on locale mismatch, activating the flag path with f_ctp NULL). Escalation closed: READ-only primitive confined to first page; page 0 is user-mappable on this guest so no forced panic and code becomes attacker-chosen, but every sink of code is a bounded <= 3-byte conversion output - no write-what-where, no leak, no uid 0 chain.",
  "recommended_fix": "guard dp->d_table[c1] == NULL with ret=-1 break immediately before the line 192 load, mirroring the existing line 163 check (see fix.diff)",
  "fix_status": "fixed",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 + patched libiconv.ko sha256 30bfdffe7430d3524e832faaa0cdc13622194b0e20022373658982a65f119642",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Single-guard fix.diff applied to guest /usr/src, libiconv.ko rebuilt and hash-verified, disassembly shows test %rdi,%rdi je break before the previously unguarded load. Same armed tables and same harness: control conversions bit-identical (41 42, 63, 12 34), single-byte and double-byte triggers both return ret=-1 with 0 bytes consumed/produced (identical to a normal unconvertible char), zero Fatal traps in the patched boot.",
  "fix_evidence": "fix_run.log (sha256 line + armed pairs + km0/km1/km2 all load, df2237 dmesg showing SURVIVED ret=-1 for both triggers), fix_build.log (patched module compile+link), fix_boot.log (whole boot, no Fatal trap), fix.diff"
}
