# VERDICT — DF-4615

**Status: not_reproduced** — no copperhead (0x1014:0x002E/0x0250) ServeRAID
controller on the audit guest (`env.txt`), and QEMU ships no device model for
one, so the interrupt path cannot be entered. Static trace is complete and
line-accurate; confidence certain.

## Proof

1. **Failure frees the queue but keeps the pointer.**
   `ips_copperhead_queue_init` (ips.c:629-676): after `bus_dmamem_alloc`
   succeeds (ips.c:650), any later failure (`base_phys_addr == 0` at
   ips.c:662) goes to `exit:` which calls
   `bus_dmamem_free(dmatag, sc->copper_queue, dmamap)` (ips.c:673) and
   `bus_dma_tag_destroy(dmatag)` (ips.c:674) — **`sc->copper_queue` keeps
   pointing at the freed mapping**, the local dmatag/dmamap are destroyed.

2. **The only caller ignores the result.**
   `ips_copperhead_reinit` (ips.c:730): `ips_copperhead_queue_init(sc);` —
   no check, reinit returns 0 (success) as long as the card posts.

3. **The next interrupt walks the freed queue.**
   `ips_copperhead_intr` (ips.c:770-777) on `COPPER_SCE_BIT` →
   `ips_copperhead_cmd_status` (ips.c:745-760):
   - `sc->copper_queue->nextstatus++` — **UAF write** in ithread context;
   - `sc->copper_queue->status[statnum]` — **UAF read** (the completion
     status the driver trusts);
   - `ips_write_4(sc, COPPER_REG_SQTR, sc->copper_queue->base_phys_addr +
     4*statnum)` — card register write driven by freed-memory contents
     (stale/garbage phys address handed to hardware).

   Because the status-queue semantics feed `status.fields.command_id` into
   `sc->commandarray[cmdnumber]` (ips.c:772, the DF-1758 indexing), a freed
   then reused queue chunk corrupts the completion pipeline outright.

4. **Leak on success.** Each `ips_copperhead_reinit` (every forced watchdog
   reset, ips.c:355) allocates a brand-new queue at ips.c:650 while the old
   `sc->copper_queue` mapping + tag are never released — one ~528-byte
   DMA-mapped block and one tag leaked per reset. A card that flaps under the
   watchdog bleeds kernel memory indefinitely.

5. **NULL-deref variant:** if `bus_dma_tag_create` itself fails (ips.c:636),
   the exit path runs `bus_dmamem_free(NULL, NULL, NULL)` (ips.c:672-674) —
   NULL tag deref panic.

## Impact
Interrupt-context UAF read/write + hardware register write from freed memory
(error path), and unbounded DMA-memory leak on repeated watchdog resets
(success path). Precondition: copperhead ServeRAID hardware plus (for the
UAF) a queue-map failure during reinit. Low severity: resource-failure
trigger, no unprivileged reachability, realistic worst case kernel crash /
memory exhaustion on failing hardware. (The DF-1758 command-id OOB already
gives a malicious card strictly more power on this hardware; DF-4615 matters
for *non-malicious* failing cards.)

## Fix
Check the return of `ips_copperhead_queue_init` in `ips_copperhead_reinit`
and fail the reinit; NULL `sc->copper_queue` after freeing; free the previous
queue before allocating a new one. See `fix.diff`.

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
