# DF-3984 — sbp(4): ORB matching is address-only across ORB lifetimes — replayed mgm status completes a recycled *command* ORB (premature dmamap_unload under live device DMA + spurious CCB completion)

## Where
`sys/dev/disk/sbp/sbp.c` — matching logic:
- `OCB_MATCH(o,s)` = `o->bus_addr == ntohl(s->orb_lo)` (sbp.c:156) — the
  SBP status block carries only the low 32 bits of the ORB address; no
  source/sequence/generation discrimination beyond `src`.
- mgm completion: `sbp_recv1` sbp.c:1597-1603 matches `target->mgm_ocb_cur`
  by address, clears `mgm_ocb_cur`, later `sbp_free_ocb(sdev, ocb)`
  (sbp.c:1782) returns the OCB slot to `free_ocbs` — the slot keeps its
  `bus_addr` (fixed: `sdev->dma.bus_addr + ... + sizeof(sbp_ocb)*i`,
  sbp.c:519-522).
- command completion: `sbp_dequeue_ocb` (sbp.c:2584-2615) matches **any**
  OCB on `sdev->ocbs` by the same address test, then unloads the data
  dmamap (sbp.c:2597-2598) and `xpt_done`s the CCB (sbp.c:1774).

## The flaw
A hostile device (or hostile bus peer writing the initiator's status FIFO —
physical-request writes are enabled by default per DF-1009) can **replay**
a management-ORB status (same `orb_lo`) *after* the mgm OCB was completed
and recycled into a command OCB. The replay:
1. misses `mgm_ocb_cur` (already NULL),
2. falls through to `sbp_dequeue_ocb` (sbp.c:1605) and **matches the
   recycled command OCB by its inherited bus_addr**,
3. `bus_dmamap_unload` (sbp.c:2597) while the device may still be
   DMA-transfering that command's buffer (pages can be freed/reused →
   device writes land in unrelated memory),
4. completes the CCB with attacker-chosen status fields (sbp_status is
   fully device-controlled; `resp=0,dead=0,len<=1,status=0` yields
   CAM_REQ_CMP) — the real completion later finds "No ocb on the queue"
   (sbp.c:1606-1610) and the mismatched data is never delivered.

## Distinguishing from knowns
DF-2516 covers *payload length* validation (stale heap contents driving the
same parse). This finding is the *address-only lifetime* flaw: even a
perfectly received status block completes the wrong (recycled) ORB. No
prior finding covers ORB-identity across recycling.

## Severity
Medium: hostile-device-gated; premature `dmamap_unload` under live DMA is a
memory-disclosure/corruption primitive; spurious completions corrupt I/O
integrity. Source-certain; hardware-gated runtime (no FireWire on the audit
guest — `../DF-3981/env.txt`) → inconclusive end-to-end.

## Fix
`fix.diff` — per-LUN single-deep stale-address filter: when a management
ORB completes, remember its `bus_addr` in `sdev->stale_orb_lo`;
`sbp_dequeue_ocb` ignores (and reports) a matching stale address once,
preventing the replay from ever matching the recycled command OCB.
