DF-3962 / verdict.json
{ "finding_id": "DF-3962", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "Certain source-level race: hptiop_post_req_mvfrey arms a 20s per-CCB callout (hptiop.c:2647-2650) whose handler hptiop_reset_adapter (2244-2250) polls iop_intr via hptiop_send_sync_msg (899-906) WITHOUT hba->lock, while hptiop_pci_intr (2163-2169) runs the same iop_intr WITH the lock; the mvfrey outlist drain (782-795) uses the shared non-atomic outlist_rptr, so concurrent execution completes the same tag twice -> hptiop_free_srb twice (freelist aliasing, two CCBs share one srb) and xpt_done(ccb) twice (CAM UAF). Also: the timed-out CCB is never completed (callout arg is hba), and the reset busy-waits up to 60s in softclock. Siblings hptmv/hpt27xx lock in their timeout handlers. Not reproduced: no mvfrey HBA on the audit guest (env.txt).", "exploit_chain": "mvfrey command stalls >20s while later completions arrive -> callout fires hptiop_reset_adapter on CPU0 (unlocked) as a completion IRQ arrives on CPU1 (locked) -> both drain the same outlist entry -> double srb completion -> srb appears twice on the free list -> next two posts alias one request buffer (16-byte-stride descriptor corruption between commands) and double xpt_done panics or corrupts CAM state; independently the 60s DELAY loop in softclock stalls the CPU (DoS).", "evidence": "VERDICT.md (path:line race chain + sibling comparison), trigger.c (source excerpt + hardware recipe), env.txt, fix.diff (lock acquisition, git apply --check clean)", "kernel_refs": [ "sys/dev/raid/hptiop/hptiop.c:2647", "sys/dev/raid/hptiop/hptiop.c:2244", "sys/dev/raid/hptiop/hptiop.c:891", "sys/dev/raid/hptiop/hptiop.c:899", "sys/dev/raid/hptiop/hptiop.c:2163", "sys/dev/raid/hptiop/hptiop.c:782", "sys/dev/raid/hptiop/hptiop.c:634", "sys/dev/raid/hptiop/hptiop.c:639", "sys/dev/raid/hptmv/entry.c:2626", "sys/dev/raid/hpt27xx/hpt27xx_osm_bsd.c:530" ], "poc_changes": "No runnable PoC: needs an mvfrey-family HBA (RR43xx/45xx) with a stalled command and concurrent completion; trigger.c carries the annotated source chain and hardware recipe.", "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": 8, "guest_dirty": 0, "build_cmd": "guest: cd /usr/src/sys/dev/raid/hptiop && patch -p1 < fix.diff && make # after make obj", "run_cmd": "dfbsd-qemu/vm.sh run_root pciconf -lv | grep -i 1103; ls -la /boot/kernel/hptiop.ko", "code_hash": "3910c9facb7bf99b56840392e91f2fdc095d9676c5d278579182ccab67ffc8d3", "notes": "Pass-2 finding (deeper than DF-1311..1313: multi-path lifetime/race analysis). Lock is LK_CANRECURSE (hptiop.c:1899) so the fix works for both the callout and XPT_RESET_BUS paths.", "recommended_fix": "Take hptiop_lock_adapter in hptiop_reset_adapter before send_sync_msg (fix.diff); upstream should additionally complete/abort the timed-out CCB and drop the 60s callout-context busy-wait.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff serializes the callout-driven iop_intr with the hard-IRQ path by acquiring the recursive adapter lock in hptiop_reset_adapter; git apply --check passes against pristine sys/. Runtime validation impossible without the HBA fix.diff applied to the guest /usr/src copy and the hptiop.ko module rebuilt clean with -Werror (build.log; combined with the other four hptiop fix.diffs of this batch); runtime validation still impossible without the HBA.", "fix_evidence": "fix.diff (git apply --check clean); fix.diff applied to the guest /usr/src copy and the hptiop.ko module rebuilt clean with -Werror (build.log; combined with the other four hptiop fix.diffs of this batch); runtime validation still impossible without the HBA." } |