# DF-2474 — Stale base pointer in isp_pci_mbxdma error cleanup

## Verdict: NOT REPRODUCED (HW-gated) — source bug CONFIRMED

## Hardware gate

No QLogic ISP HBA in guest: `kldstat` shows only kernel/ehci/xhci; `pciconf -l`
shows no QLogic device. The isp PCI attach path is never exercised.

## Source trace (confirmed real bug)

**File:** `sys/dev/disk/isp/isp_pci.c:1600-1673`

`isp_pci_mbxdma()` uses a single local `caddr_t base` for both the control-area
allocation (line 1600) and every per-channel FC scratch allocation (line 1629).
The FC loop overwrites `base` on each iteration. When any later step fails (e.g.,
`bus_dmamap_create` ENOMEM in the per-command map loop at line 1646-1655), control
reaches `bad:` at line 1667. The cleanup loop (1668-1672) frees every FC channel
using the **same stale `base`** (last channel's address), and the final control-area
free at line 1673 also uses the stale `base`. Result: double/triple-free of one
channel's virtual address; leak of every other allocation.

## Fix

- Added `caddr_t ctrl_base` to save the control-area base before the FC loop
- Added `caddr_t rscratch` field to `struct isp_fc` to store each channel's base
- bad: cleanup uses `fc->rscratch` for per-channel frees and `ctrl_base` for the
  control-area free

Spans `isp_freebsd.h` and `isp_pci.c`. See `fix.diff`.

## Impact (on HW that has the HBA)

Medium — kernel-heap double-free primitive on error cleanup paths.
