โฌข DragonFlyBSD Kernel Audit
DF-3962 / trigger.c
โ† back to finding โ†“ download raw
/*
 * DF-3962 trigger sketch โ€” mvfrey CCB-timeout callout races the IRQ handler
 * ========================================================================
 * hptiop_post_req_mvfrey() arms a 20 s per-CCB timeout:
 *
 *   hptiop.c:2647  if (req->header.type == IOP_REQUEST_TYPE_SCSI_COMMAND) {
 *   hptiop.c:2648      callout_reset(ccb->ccb_h.timeout_ch, 20 * hz,
 *   hptiop.c:2649                    hptiop_reset_adapter, hba);
 *
 * The callout fires hptiop_reset_adapter(hba) (hptiop.c:2244-2250) which runs
 * hptiop_send_sync_msg() -> hba->ops->iop_intr(hba) (hptiop.c:899-906) WITHOUT
 * taking hba->lock, while the hard interrupt path hptiop_pci_intr()
 * (hptiop.c:2163-2169) runs the very same iop_intr holding the lock.
 *
 * hptiop_intr_mvfrey() (hptiop.c:782-795) drains the shared outlist using the
 * NON-atomic hba->u.mvfrey.outlist_rptr:
 *   do { cptr = *outlist_cptr & 0xff;
 *        while (rptr != cptr) { rptr++; _tag = outlist[rptr].val;
 *                               hptiop_request_callback_mvfrey(hba,_tag); } }
 *   while (cptr != (*outlist_cptr & 0xff));
 *
 * Two CPUs executing this concurrently (callout on CPU0 unlocked, IRQ on CPU1
 * locked) both observe rptr != cptr, both read the SAME outlist entry, both
 * call hptiop_request_callback_mvfrey(_tag) for the same tag ->
 *   srb = hba->srb[(_tag>>4)&0xff] completed TWICE:
 *     - hptiop_free_srb(hba, srb) twice  -> srb on freelist twice
 *       -> two live CCBs share one srb -> cross-command corruption
 *     - xpt_done(ccb) twice             -> CAM UAF on the ccb
 *     - bus_dmamap_unload(dma_map) twice
 *
 * Second leg: the timed-out CCB itself is NEVER completed by the timeout
 * handler (the callout arg is hba, not the ccb) โ€” if the reset does not make
 * the firmware complete the request, the ccb hangs forever (CAM wedge).
 *
 * Third leg: hptiop_send_sync_msg(RESET, 60000) busy-loops DELAY(1000) up to
 * 60 s inside softclock โ€” starves the callout CPU, trips watchdogs.
 *
 * Compare the sibling HighPoint drivers, whose timeout handlers DO lock:
 *   sys/dev/raid/hptmv/entry.c:2626-2633  hpt_timeout(): lock_driver(); fResetVBus()
 *   sys/dev/raid/hpt27xx/hpt27xx_osm_bsd.c:530-532
 *
 * Trigger on hardware: stall one mvfrey device (RR 43xx/45xx) โ€” e.g. saturate
 * it and hot-unplug/expel it, or let the MCU wedge โ€” so that a SCSI command
 * outruns its 20 s timeout while later completions still arrive.
 */
int main(void) { return 0; }  /* informational sketch โ€” see VERDICT.md */