DF-3844 / verdict.json
{ "finding_id": "DF-3844", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "Source-certain lifetime defect: mrsas_issue_blocked_cmd (mrsas.c:2865-2900) returns after its 180 s timeout without aborting the firmware-owned command, and every caller (mrsas.c:566-573, 3058-3059, 3098-3099; mrsas_ioctl.c:301+367 which ignores the return) immediately releases the mfi cmd back to the free pool. A late firmware completion then routes through mrsas_complete_cmds PASSTHRU case (mrsas.c:1294-1299) onto the recycled command; if the recycler issued a RAID-map sync DCMD, mrsas_complete_mptmfi_passthru releases the command again (mrsas.c:2953/2960) while its new owner still waits, double-inserting it into mrsas_mfi_cmd_list_head (mrsas.c:2578) \u2014 two threads subsequently get the same mfi cmd, and the endpoint is a double completion/double xpt_done of a shared ccb. mrsas_reset_ctrls re-fire loop (mrsas.c:2448-2470) re-fires wrappers whose mfi cmd was already released by a timed-out waiter (no ownership check). The shared sleep ident sc->chan (mrsas.c:2880-2888, 3011-3012) additionally lets wakeup_one wake the wrong waiter. Not executable on the audit guest: mrsas is compiled into the kernel but no LSI HBA exists (no /dev/mrsas*), and manifestation additionally needs firmware that stalls a passthrough >180 s while a second ioctl recycles the command.", "exploit_chain": "operator-group ioctl A stalls in FW; A times out at 180 s and releases its mfi cmd; ioctl B (or driver map sync) recycles it; FW completes A late; stale completion wakes B with wrong status or double-releases the map-sync cmd; pool list contains the cmd twice; two later ioctl threads obtain the same mfi cmd; concurrent frame writes + double completion -> corrupted pool / double xpt_done (ccb UAF). Timing-gated, requires the HBA.", "evidence": "VERDICT.md interleaving with path:line for each step; run.log guest presence check (driver in kernel, no HBA, no /dev/mrsas*); df3844_trigger.c outline for equipped hardware.", "kernel_refs": [ "sys/dev/raid/mrsas/mrsas.c:2865", "sys/dev/raid/mrsas/mrsas.c:2887", "sys/dev/raid/mrsas/mrsas.c:2893", "sys/dev/raid/mrsas/mrsas.c:2571", "sys/dev/raid/mrsas/mrsas.c:1294", "sys/dev/raid/mrsas/mrsas.c:2913", "sys/dev/raid/mrsas/mrsas.c:2945", "sys/dev/raid/mrsas/mrsas.c:2953", "sys/dev/raid/mrsas/mrsas.c:2960", "sys/dev/raid/mrsas/mrsas.c:3011", "sys/dev/raid/mrsas/mrsas.c:2448", "sys/dev/raid/mrsas/mrsas.c:2821", "sys/dev/raid/mrsas/mrsas_ioctl.c:301", "sys/dev/raid/mrsas/mrsas_ioctl.c:367", "sys/dev/raid/mrsas/mrsas_cam.c:1080" ], "poc_changes": "No seed PoC; authored df3844_trigger.c sketch. Cannot be built/run meaningfully without /dev/mrsas0 (open() fails on the guest \u2014 recorded).", "attempts": 1, "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": 12, "guest_dirty": 0, "build_cmd": "cc -o df3844_trigger df3844_trigger.c (skipped: open(/dev/mrsas0) cannot succeed without HBA)", "run_cmd": "kldstat -v | grep -i mrsas; pciconf -lv | grep -i megaraid; ls /dev/mrsas*", "code_hash": "3298a857f6ec38c807018018f7098a693c1ca4db404757613f7b03ab06888687", "notes": "DF-3673/DF-3710 family (mpt timeout-vs-completion, arcmsr double-completion) applied to mrsas mfi cmds. The late-completion handler dereferences cmd_mfi = mfi_cmd_list[sync_cmd_idx] (in-bounds index) \u2014 the defect is release-while-owned, not a wild pointer; memory-safety endpoint is the duplicated free-list entry followed by double completion.", "recommended_fix": "On timeout, abort the command at the firmware before returning to callers that release it, and use a per-command sleep ident (tsleep(cmd)/wakeup_one(cmd)) instead of the shared sc->chan.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff (a) issues an abort on timeout so no caller releases a firmware-owned cmd, (b) fixes the wrong-waiter wakeup by keying the sleep channel on the cmd pointer, (c) makes mrsas_passthru honor the timeout return. Cannot be validated on a guest without the HBA -> not_testable.", "fix_evidence": "fix.diff three hunks (mrsas.c timeout abort + per-cmd ident; mrsas_ioctl.c return check)." } |