DF-4835 / verdict.json
{ "finding_id": "DF-4835", "status": "reproduced", "reproduced": 1, "impact": "panic", "confidence": "certain", "verdict": "REPRODUCED (harness; guest has no mrsas controller \u2014 DF-4559 methodology). mrsas_alloc_mfi_cmds()s create_frame_pool failure path (mrsas_ioctl.c:424-431) frees every allocated MFI frame via mrsas_free_frame() \u2014 which never clears cmd->frame_mem/frame_phys_addr (:532-538) \u2014 and destroys sc->mficmd_frame_tag without NULLing it, leaving sc->mfi_cmd_list populated with dangling pointers, then returns ENOMEM. mrsas_init_fw (mrsas.c:1719) propagates, attach unwinds via attach_fail_fw (:800,:842) into mrsas_free_mem(), which calls mrsas_free_frame() on all 32 cmds again (mrsas.c:1011-1016): bus_dmamap_unload through the freed tag (UAF) + bus_dmamem_free of already-freed frame memory (double free per frame), then a second bus_dma_tag_destroy (:1017-1018, double kfree of segments+tag). Harness replicates the verbatim sequence with a freed-tracking allocator: baseline reports 5 UAF tag touches, 5 frame double-frees and the tag double-free (HEAP CORRUPTION, exit 42); fixed model (error path leaves cleanup to mrsas_free_mem) runs clean. Attach-time, OOM-gated (BUS_DMA_NOWAIT failure) \u2014 Low severity per DF-4438 convention, but a genuine kernel heap double-free chain.", "exploit_chain": "driver attach under kernel memory pressure -> mrsas_create_frame_pool bus_dmamem_alloc/load NOWAIT failure at cmd i -> error path frees frames 0..i-1 + destroys tag, pointers left dangling -> mrsas_free_mem second pass double-frees each frame and the tag -> kernel heap corruption (panic-grade); exploitability limited: requires OOM at attach and heap grooming between the two free passes.", "evidence": "run.log: ** USE-AFTER-FREE touch of freed 0x8004908c0 (tag, per frame), ** DOUBLE FREE of 0x8004a8400/0x8004a8000/0x8004a7c00/0x8004a7800/0x8004a7400 (frames 0..4), ** DOUBLE FREE of 0x8004908c0 (tag), mrsas_free_mem: HEAP CORRUPTION ... exit=42; FIXED arm mrsas_free_mem: clean, exit 0. VERDICT.md has the path:line trace.", "kernel_refs": [ "sys/dev/raid/mrsas/mrsas_ioctl.c:424", "sys/dev/raid/mrsas/mrsas_ioctl.c:428", "sys/dev/raid/mrsas/mrsas_ioctl.c:532", "sys/dev/raid/mrsas/mrsas.c:842", "sys/dev/raid/mrsas/mrsas.c:1011", "sys/dev/raid/mrsas/mrsas.c:1017" ], "poc_changes": "No seed PoC (pass-2 new finding). Harness written from scratch; DFlys jemalloc does not abort on double free, so the mock allocator tracks freed pointers explicitly (kfree_real/kmcheck) to detect every double-free/UAF deterministically; failure injected at cmd #5.", "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": 90, "guest_dirty": 0, "build_cmd": "cc -O2 -Wall -o df4835 df4835_harness.c", "run_cmd": "./df4835 && ./df4835 fixed", "code_hash": "f004e623938575bb85808732899cf397527d76c9ea2287786e41a58a0735eeb3", "notes": "Distinct from DF-1921 (passthru early-return resource LEAKS at :193-250) \u2014 this is the alloc_mfi_cmds/create_frame_pool attach path DOUBLE-FREE; distinct from DF-4438 (mrsas_cam attach sims). DFly busdma factored in: bus_dmamem_alloc maps are not tag map_count-ed, so the :428 destroy succeeds (busdma_machdep.c:334-346).", "recommended_fix": "In the create_frame_pool failure path, do not free frames or destroy the tag \u2014 leave them for the callers mrsas_free_mem() unwind (fix.diff in pack)", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Validated with the harness fixed-model arm (error path leaves frames+tag alive; mrsas_free_mem performs the single free pass): mrsas_free_mem: clean ... exit=0 vs baseline exit=42 with 11 corruption events. fix.diff not applied to the read-only sys/ tree; kernel-build validation not meaningful without an mrsas controller in the guest.", "fix_evidence": "run.log FIXED section: mrsas_free_mem: clean (use-after-free/double-free detected: no) / [FIXED ] child exit=0; fix.diff in pack." } |