DF-3124 / verdict.json
{ "finding_id": "DF-3124", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "Reproduced deterministically twice from fresh boots: mounting a cd9660 filesystem with ISOFSMNT_KICONV while the charset pair fails to open (iconv_open returns ENOENT, return value ignored at cd9660_vfsops.c:494-495) leaves im_d2l/im_l2d NULL; the first namei under the mount reaches sgetrune()/isochar() -> iconv_convchr(NULL) -> KOBJ ops load from address 0 -> Fatal trap 12, fault virtual address = 0x0, Stopped at iconv_convchr+0x27: movq (%rdi),%rsi. Baseline mount without kiconv on the same image is clean. NULL-deref DoS only: the faulting pointer is fixed NULL, no write primitive, no escalation.", "exploit_chain": "", "evidence": [ "run.log: [+] mount succeeded with ISOFSMNT_KICONV and failed iconv_open (im_d2l == im_l2d == NULL) followed by ssh death and vm.sh status=down", "panic.txt: Fatal trap 12: page fault while in kernel mode / fault virtual address = 0x0 / Stopped at iconv_convchr+0x27: movq (%rdi),%rsi (both runs)", "run.log baseline section: same image mounts cleanly and stat returns ENOENT without kiconv", "VERDICT.md: line-accurate root-cause trace vfsops.c:494-495 -> cd9660_util.c sgetrune -> iconv.c:290" ], "kernel_refs": [ "sys/vfs/isofs/cd9660/cd9660_vfsops.c:494", "sys/vfs/isofs/cd9660/cd9660_vfsops.c:495", "sys/vfs/isofs/cd9660/cd9660_vfsops.c:584", "sys/vfs/isofs/cd9660/cd9660_util.c:sgetrune", "sys/vfs/isofs/cd9660/cd9660_lookup.c:237", "sys/libiconv/iconv.c:290" ], "poc_changes": "No seed pack existed; authored from scratch: hand-crafted 40-sector minimal ISO9660 image (PVD s16, terminator s17, root dir extent s18) plus a direct mount(2) caller using ISOFSMNT_KICONV with empty cs_local/cs_disk (the same state mount_cd9660 -o kiconv produces, since set_charset() only runs for -C).", "attempts": 2, "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": 480, "guest_dirty": 0, "build_cmd": "cc -O -o /root/trigger /root/trigger.c -I/usr/src/sys", "run_cmd": "vnconfig -c -S 2048 /dev/vn0 /root/poc.iso; kldload libiconv; kldload cd9660_iconv; /root/trigger", "code_hash": "25aa27c7f17411e37a36a913f18ee7c488b13ba149b9b8fb71b8d906e9524811", "notes": "Mount requires root/SYSCAP_RESTICTEDROOT (get_fscap cd9660 -> SYSCAP_RESTRICTEDROOT, vfs_syscalls.c:5397), but the panic itself is triggerable by ANY local user via plain stat()/ls under such a mount. cd9660_unmount() already NULL-checks the handles, proving the NULL state is anticipated. Severity Low (privileged opt-in, DoS).", "recommended_fix": "Check both cd9660_iconv->open() returns; on failure close the half-opened handle, NULL both handles and clear ISOFSMNT_KICONV so isochar()/sgetrune() take their non-iconv fallback; force NUL-termination of cs_local/cs_disk (see fix.diff).", "fix_status": "not_testable", "fix_kernel_uname": "", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored post-verification (guarded fallback mirroring cd9660_unmounts NULL discipline + charset NUL-termination). Kernel-rebuild fix-validation skipped by policy: Low-severity NULL-deref DoS, not a Critical/High or memcorrupt/privesc finding; the conditional-verify scope reserves the rebuild cycle for those.", "fix_evidence": "fix.diff in this pack" } |