# VERDICT — DF-4614

**Status: not_reproduced** for the in-kernel bug (the audit guest has no IBM
ServeRAID controller — `env.txt`; the ips driver is linked into the kernel
but never attaches, `/dev/ips*` absent). **The control flow itself was
demonstrated on the DragonFly guest** with `doublefree_harness.c`: the exact
call sequence reaches a double `kfree` of `sc->commandarray` and an
intervening use-after-free read (`run.log`: `[!] DOUBLE FREE: kfree(#2) …
exit=42`). Confidence in the code defect: certain.

## Root cause (line-accurate)

1. `ips_cmdqueue_free()` frees unconditionally and leaves the dangling
   pointer (ips.c:139-141):

   ```c
   sc->staticcmd = NULL;
   kfree(sc->commandarray, M_IPSBUF);   /* NOT sc->commandarray = NULL */
   ```

   and the `kfree` runs **outside** the `used_commands == 0` guard
   (ips.c:122-138), so it also frees the array while commands are in flight
   (detach/unload case; ips_adapter_free then returns EBUSY with the driver
   still loaded on a freed array, ips.c:533-537).

2. `ips_adapter_init()` ignores the first init's failure (ips.c:414):

   ```c
   sc->max_cmds = 1;
   ips_cmdqueue_init(sc);      /* <-- return value discarded */
   ```

   The failed init already ran `ips_cmdqueue_free` internally (ips.c:190)
   and set `IPS_OFFLINE` (ips.c:137). Because the card itself is healthy,
   `ips_adapter_reinit(sc, 0)` (ips.c:416) succeeds; the next card command
   (`ips_ffdc_reset` → `ips_get_free_cmd`, ips.c:421) returns EIO due to
   IPS_OFFLINE → `goto error` (ips.c:424) → `ips_adapter_free` (ips.c:462)
   → `ips_cmdqueue_free` **again** (ips.c:533):
   - ips.c:124-125: `command->command_phys_addr` read from freed memory
     (**UAF read**);
   - if nonzero, ips.c:127-134 `bus_dmamap_unload` + `bus_dmamem_free` +
     `bus_dmamap_destroy` on stale/garbage pointers (**arbitrary free**);
   - ips.c:140: second `kfree(sc->commandarray)` (**double free**).

3. Second trigger with identical shape: the *checked* re-sized init at
   ips.c:447-451 fails internally → `goto error` → same double free via
   ips.c:462 → 533.

## Harness fidelity

`doublefree_harness.c` copies the decision structure of ips.c:116-143 and
ips.c:374-464 verbatim (with the bus_dma layer stubbed to force the ips.c:167
failure). Compiled and run **on the audit guest** (DragonFly 6.5-DEVELOPMENT,
cc): `build.log`, `run.log`. Output `exit=42` is the harness's allocator
aborting on the second free of the same pointer — the point at which the real
kernel allocator's free lists would be corrupted.

## Impact

Kernel heap double-free / use-after-free in the boot-time attach path (Triggers
A/B) and in the detach path (Trigger C). Consequences: memory corruption
(crash → exploitable heap state in principle; attacker control of the trigger
is limited to forcing DMA-map exhaustion during attach and concurrent I/O
during detach). Precondition: IBM ServeRAID PCI hardware present. Severity
Medium (certain code path, constrained trigger, no unprivileged reachability).

## Why not reproduced in-kernel on the guest

`env.txt`: `pciconf -l` shows no vendor 0x1014/0x9005 device; `/dev/ips*`
does not exist; the driver never probes. QEMU has no ServeRAID device model,
so `ips_attach` cannot be entered. A fault-injected kernel build (forcing
bus_dmamem_alloc to fail) would change no conclusion beyond what the harness
already proves — the call graph after the injected failure is fully static.

## Fix

* NULL out `sc->commandarray` after kfree and skip the walk when it is NULL;
* guard the kfree with the `used_commands == 0` condition and return EBUSY
  *before* freeing anything when commands are outstanding;
* check the return of the first `ips_cmdqueue_init` (ips.c:414) and bail out
  immediately.

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.
