DF-5536 / verdict.json
{ "finding_id": "DF-5536", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "The dump walk uses kernel page-table frames without validation: dump_add_page(pdp[i]&PG_FRAME) at :260 and dump_add_page(pd[j]&PG_FRAME) at :281 are not is_dumpable-guarded (unlike the leaf paths at :271/:291), dump_add_page/dump_drop_page (:452/:463) have no bitmap bounds check, and :263/:285 DMAP-read the same raw frames. Demonstrated on the live guest by planting a single fake PDP entry: frame 2^47 yields Fatal trap 12: page fault while in kernel mode, fault virtual address = 0xfffff80140000000 (= vm_page_dump[frame>>18]), supervisor write data -> nested panic, wedged guest, no dump; frame 2^46 silently bit-ORs a live kernel object 2GB past the bitmap and crashes later with vm_object_hold_shared(NULL). Precondition is kernel page-table corruption (post-exploitation or the original crashing bug), so no privilege boundary is crossed - severity Low - but the dump writer turns corrupted PTEs into an uncontrolled kernel write / loss of the crash dump exactly when forensics matter.", "exploit_chain": "requires prior kernel memory corruption (attacker already ring-0): plant PDP/PD entry with chosen frame -> panic -> dump walk calls dump_add_page(frame) -> atomic_set_long at vm_page_dump + frame/32KB (chosen offset, bit-OR, 8-byte aligned) -> silent kernel-memory corruption or page fault; demonstrated both outcomes", "evidence": "panic.txt: Fatal trap 12, fault VA 0xfffff80140000000 matching the rig-predicted &vm_page_dump[0x20000000], supervisor write data, page not present, panic: page fault, no dump. panic.2-silent-corruption.txt: frame 2^46 -> nested panic: assertion obj != NULL failed in vm_object_hold_shared. run.patched.log: patched kernel, identical plant -> Dump complete.", "kernel_refs": [ "sys/platform/pc64/x86_64/minidump_machdep.c:260", "sys/platform/pc64/x86_64/minidump_machdep.c:263", "sys/platform/pc64/x86_64/minidump_machdep.c:281", "sys/platform/pc64/x86_64/minidump_machdep.c:285", "sys/platform/pc64/x86_64/minidump_machdep.c:452", "sys/platform/pc64/x86_64/minidump_machdep.c:463", "sys/vm/vm_page.c:399" ], "poc_changes": "PoC authored fresh: KLD rig plants pdp[64]=frame|V in an unused kernel PDP slot (chosen far beyond kernel_vm_end after a first attempt in the first-free slot was disturbed by panic-time allocations) and panics via sysctl trigger.", "attempts": 4, "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 (baseline); #1: Wed Oct 7 03:43:23 UTC 2026 (patched)", "runtime_sec": 2700, "guest_dirty": 1, "build_cmd": "cd /root/mddiag && make obj >/dev/null 2>&1 && make && cp /usr/obj/root/mddiag/mddiag.ko .", "run_cmd": "kldload /root/mddiag/mddiag.ko; sysctl debug.debugger_on_panic=0; sysctl debug.mddiag=booby", "code_hash": "4417cc4784717abb94cb42c21f08e0c8d61111a275440c77f698b42af4a4982e", "notes": "Both fault variants reproduced from fresh boots; the fault VA matched the predicted bitmap OOB target byte-for-byte and the fault was a supervisor WRITE (the atomic_set_long), proving direct attribution to minidump_machdep.c:260->:459. Fixed kernel validated with the identical rig.", "recommended_fix": "is_dumpable() guards on the PD/PT frames at :260/:281 (before any use, incl. the DMAP reads) plus a bitmap bounds check in dump_add_page/dump_drop_page (also fixes int idx truncation for pa >= 2^49).", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 1, "fix_verdict": "Applied fix.diff in the guest /usr/src, rebuilt and rebooted into the patched kernel; the identical booby run now skips the planted entry (is_dumpable(frame)==0) and completes the dump normally instead of Fatal-trap-12ing - bad behavior gone.", "fix_evidence": "run.patched.log: Dumping 668 MB ... Dump complete on the patched kernel with pdp[64]=0x800000000000|V planted (baseline: Fatal trap 12 + nested panic + no dump)" } |