DF-3892 / verdict.json
{ "finding_id": "DF-3892", "status": "not_reproduced", "reproduced": 0, "impact": "none", "confidence": "certain", "verdict": "cm_callout is initialized with callout_init_mp (sys/dev/raid/mps/mps.c:860) \u2014 DragonFlys lock-free MP-safe callout (kern_timeout.c:626-631 runs the callback with no lock) \u2014 but the callback armed on it for every SCSI IO (mps_sas.c:1768) is mpssas_scsiio_timeout, whose second statement is KKASSERT(lockowned(&sc->mps_lock)) (mps_sas.c:1490) and which then runs mps_intr_locked() lock-free (mps_sas.c:1499). On every stock DragonFly kernel (X86_64_GENERIC ships options INVARIANTS, and KKASSERT is a real panic, sys/sys/systm.h:98-101) the FIRST SCSI IO timeout on an mps(4) adapter deterministically panics the kernel; on non-INVARIANTS builds the callback races the interrupt threads lock-held completion paths (replypostindex/timedout_commands/command free) with list-corruption/UAF potential. The sibling mpr(4) driver uses callout_init_lk(&cm->cm_callout, &sc->mpr_lock) (mpr.c:1539) with assert-style timeout callbacks \u2014 proving mps_sas.c was written against the lock-tied discipline but initialized the callout wrong. Not reproduced on the guest: mps driver is compiled in (pci/mps in kldstat -v) but QEMU has no LSI SAS2 PCI device, so the SIM never attaches and no command timeout can be armed; defect certain from source.", "exploit_chain": "", "evidence": "VERDICT.md (path:line proof incl. kern_timeout.c callback dispatch and GENERIC INVARIANTS), env.txt (no SAS2 HBA, mps unattached), run.sh + run.log (hardware gate), fix.diff (callout_init_lk + assert-style tm_timeout, mirrors mpr.c:1539)", "kernel_refs": [ "sys/dev/raid/mps/mps.c:860", "sys/dev/raid/mps/mps_sas.c:1768", "sys/dev/raid/mps/mps_sas.c:1481", "sys/dev/raid/mps/mps_sas.c:1490", "sys/dev/raid/mps/mps_sas.c:1499", "sys/dev/raid/mps/mps_sas.c:1522", "sys/kern/kern_timeout.c:626", "sys/dev/raid/mpr/mpr.c:1539" ], "poc_changes": "No userland PoC can reach the driver without the HBA; run.sh records the hardware gate per the DF-3801 precedent.", "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": 15, "guest_dirty": 0, "build_cmd": "n/a", "run_cmd": "sh findings/poc/DF-3892/run.sh", "code_hash": "", "notes": "Same defect exists in upstream FreeBSD mps(4) only insofar as FreeBSD callouts differ (FreeBSD mpssas_scsiio_timeout takes the lock itself); the DragonFly port is the broken variant. First-timeout panic is deterministic on GENERIC.", "recommended_fix": "callout_init_lk(&cm->cm_callout, &sc->mps_lock) in mps.c (mirror mpr.c:1539) and convert mpssas_tm_timeout to assert the lock instead of taking it.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff applies the mpr(4) reference pattern; cannot be exercised on this guest (no SAS2 HBA).", "fix_evidence": "findings/poc/DF-3892/fix.diff" } |