โฌข DragonFlyBSD Kernel Audit
DF-3965 / trigger.c
โ† back to finding โ†“ download raw
/*
 * DF-3965 trigger sketch โ€” per-I/O dmamap unload only on IOP_RESULT_SUCCESS
 * ==========================================================================
 * hptiop_action() loads the CCB buffer into the per-SRB map for every
 * data command (hptiop.c:2304-2309). The completion callbacks unload ONLY
 * in the success case:
 *
 *   hptiop_request_callback_itl   hptiop.c:393-409   case IOP_RESULT_SUCCESS:
 *                                                   sync + bus_dmamap_unload
 *   hptiop_request_callback_mv    hptiop.c:547-561   (same shape)
 *   hptiop_request_callback_mvfrey hptiop.c:654-668  (same shape)
 *
 * Every other result โ€” BAD_TARGET, BUSY, INVALID_REQUEST, FAIL, RESET,
 * CHECK_CONDITION โ€” returns the srb to the freelist with its dma_map STILL
 * LOADED. Deterministic source of leaked loads: every bus-scan probe of an
 * absent target id completes BAD_TARGET (hptiop.c:411-412) โ€” one leaked map
 * state per probe, at attach and at every HPT_SCAN_BUS ioctl / CAM rescan.
 *
 * Consequences:
 *  - busdmamap_load() on an already-loaded map on next use of that srb
 *    (hptiop.c:2304): on bounce-capable tags/platforms the cumulative
 *    reserve/needed accounting (busdma_machdep.c:616-660) never releases the
 *    prior reservation -> hw.busdma pool exhaustion (guest: max_bpages=1024)
 *    -> permanent ENOMEM/EINPROGRESS -> CAM_BUSY forever on those srbs.
 *  - On this no-bounce io_dmat (lowaddr=BUS_SPACE_MAXADDR) the leak is
 *    bookkeeping-only on amd64, hence Low; on i-compat/32-bit configs and
 *    any tag with a real lowaddr, it strands reserved bounce pages.
 *
 * Trigger on hardware: repeatedly `camcontrol rescan all` (or the
 * HPT_DO_IOCONTROL/HPT_SCAN_BUS ioctl) on an HBA with absent target ids;
 * watch hw.busdma.total_bpages climb / maps fail.
 */
int main(void) { return 0; }