{
  "finding_id": "DF-5756",
  "status": "reproduced",
  "reproduced": true,
  "impact": "none",
  "confidence": "certain",
  "verdict": "iconv_ucs_conv() checks only the high-surrogate prefix (0xd8) on the leading UTF-16 unit (sys/libiconv/iconv_ucs.c:255) and has no surrogate check in the UTF-8 output stage (:293-312), so a lone low surrogate (U+DC00-DFFF) is accepted as an ordinary character and, given >=3 output bytes, re-encoded by ucs4_to_utf8 (:495-497, w=3) as CESU-8: the in-kernel witness converted \"\\xDC\\x00\" to ED B0 80 with ret=0 while rejecting a lone high surrogate (ret=-1) \u2014 the asymmetry. Via a crafted msdosfs KICONV image the unpaired surrogate surfaces as a silent ? substitution (dirent abcd?fghij.k) instead of an invalid-input rejection; base-system userland iconv(3) returns EILSEQ for the same bytes. No memory corruption, no leak: invalid-Unicode laundering/ parser-confusion input; severity Low. Fix (leading-DC rejection + output-stage surrogate check) rebuilt and validated: witness ret=-1 with nothing emitted, valid surrogate pairs byte-identical.",
  "exploit_chain": "crafted FAT image carries an LFN unit 0xDC00 -> msdosfs win2unixfn (msdosfs_conv.c:663-678, unit not 0 nor /) -> win2unixchr -> convchr(pm_w2u) -> iconv_ucs_conv: (*q&0xfc)==0xdc misses the 0xd8-only check (iconv_ucs.c:255) -> ucslen=2 (:264-266) -> UTF-8 second half has no surrogate check (:293-312) -> ucs4_to_utf8(0xDC00) wants w=3; with msdosfss 2-byte staging it fails dstlen<w (:505-506) -> win2unixchr substitutes ?; with a >=3-byte consumer buffer the CESU-8 bytes ED B0 80 are emitted (proven by cesu_witness.ko through the exported iconv_convchr API)",
  "evidence": "witness.log (shared with DF-5755: lowsur ret=0 out=ed b0 80; highsur-lone ret=-1); run.log (dirents abcd?fghij.k hex 61 62 63 64 3f ... and ?xyzabcd.k); logs/difftest.log (userland EILSEQ for \\xDC\\x00); logs/witness_patched.log (lowsur ret=-1 out untouched; valid-pair f0 9f 99 88 unchanged); run.patched.log",
  "kernel_refs": [
    "sys/libiconv/iconv_ucs.c:255",
    "sys/libiconv/iconv_ucs.c:264",
    "sys/libiconv/iconv_ucs.c:271",
    "sys/libiconv/iconv_ucs.c:280",
    "sys/libiconv/iconv_ucs.c:293",
    "sys/libiconv/iconv_ucs.c:299",
    "sys/libiconv/iconv_ucs.c:495",
    "sys/libiconv/iconv_ucs.c:505",
    "sys/vfs/msdosfs/msdosfs_conv.c:633",
    "sys/vfs/msdosfs/msdosfs_conv.c:946"
  ],
  "poc_changes": "authored fresh; craft5756.c initially matched full-name UTF-16LE across the LFN entry \u2014 LFN entries split names between wePart1/wePart2 with 3 metadata bytes between, so patterns were fixed to per-part with an attr==0x0f cross-check; msdosfs dirmask and DF dirent (_DIRENT_DIRSIZ) quirks as in DF-5755",
  "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": 400,
  "guest_dirty": 0,
  "build_cmd": "cc -O0 -g -Wall -I/usr/src/sys -o kread5756 kread5756.c && cc -O0 -g -Wall -o craft5756 craft5756.c",
  "run_cmd": "sh run.sh   (craft image, mount KICONV cs_local=cs_dos=UTF-8, readdir hex dump)",
  "code_hash": "2cf6a52d2cb307ff85db9f82d0eb2d416699d4bc1cc59cf68add820a3232b9a1",
  "notes": "CESU-8 bytes do not escape via msdosfs (2-byte staging); they do escape through any >=3-byte consumer of the same kernel converter (witness-proven). Upstream FreeBSD shares the defect. msdosfs-visible ? is identical pre/post fix by design \u2014 the fixs delta is at the converter level (reject vs launder).",
  "recommended_fix": "reject leading low surrogates at the input stage (extend the (*q & 0xfc) == 0xd8 check with a == 0xdc rejection) and reject code in [0xd800,0xe000) before ucs4_to_utf8 emission.",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "libiconv.ko rebuilt with fix.diff (stacked with DF-5755s) and reloaded; witness lowsur ret=-1 with output untouched (baseline: ret=0, ED B0 80); highsur-lone unchanged ret=-1; valid surrogate pair D83D DE48 still converts to f0 9f 99 88 (no regression); msdosfs readdir ?-substitution unchanged as designed (both accept-then-fail and reject-at-input surface as ? in win2unixchr \u2014 the converter now refuses invalid Unicode instead of laundering it).",
  "fix_evidence": "logs/witness_patched.log (shared DF-5755 pack); run.patched.log; logs/difftest_patched.log (userland unchanged)"
}