# DF-4420 — oce_mq_create leaks the CQ (ring DMA + struct) on two error paths

File: `sys/dev/netif/oce/oce_queue.c` (pass 2)
Severity: Info (correctness/resource leak; no unprivileged reachability)

## What happens

`oce_mq_create()` (sys/dev/netif/oce/oce_queue.c:663) creates its completion
queue FIRST (line 675) and only assigns `mq->cq = cq` on the SUCCESS path
(line 744). On two of the three failure paths the `cq` created at the top is
never destroyed:

1. `mq->ring = oce_create_ring_buffer(...)` fails -> `goto error`
   (oce_queue.c:689-691) -> `oce_mq_free(mq)`:
   - `mq->ring == NULL` -> ring block skipped (oce_queue.c:782)
   - `mq->cq == NULL` (still M_ZERO; never assigned on this path) -> CQ block
     skipped (oce_queue.c:796)
   - result: `cq` (kmalloc'd struct + oce_create_ring_buffer DMA ring created
     inside `oce_cq_create`, oce_queue.c:892-896) leaks, and
     `sc->cq[sc->ncqs-1]` (assigned in oce_cq_create:910) keeps pointing at it.

2. `oce_mbox_post()` / firmware status fails -> `goto error`
   (oce_queue.c:735-741) -> same `oce_mq_free(mq)` path:
   - the mq ring IS destroyed, but `mq->cq` is still NULL, so the CQ again
     leaks.

Only the third failure path (`kmalloc` of mq itself, oce_queue.c:681-685)
correctly calls `oce_cq_del(sc, cq)` before jumping to `error`.

## Consequences

- One-time leak of `sizeof(struct oce_cq)` + a CQ DMA ring
  (CQ_LEN_256 x sizeof(struct oce_mq_cqe) = 256 x 16 = 4 KiB DMA memory plus
  bus_dma tag/map) per failed `oce_mq_create` invocation.
- `sc->ncqs` stays incremented with a live pointer to the leaked CQ; nothing
  in the tree iterates `sc->cq[]` after `oce_queue_release_all` (checked:
  the `for_all_cq_queues` consumer macro has no callers in the teardown
  path), so this is a leak, not a UAF.
- Trigger: requires the Emulex OneConnect firmware to fail
  CREATE_MQ_EXT (or a DMA ring alloc failure) during driver attach. No
  unprivileged-user reachability; no network reachability (mailbox command,
  attach-time only).

## Why PoC was not run

- The audit QEMU guest has no Emulex BE2/BE3/Lancer hardware, so `oce(4)`
  never attaches (`pciconf -l` shows no Emulex vendor 0x19a2 device) — the
  failure path cannot be entered on the guest.
- Severity is Info (error-path resource leak, no security impact), which the
  audit contract exempts from mandatory PoC verification.
- Root cause is established by direct code reading with line-accurate
  accounting of every goto path (see VERDICT.md).

## Fix

One-line move: assign `mq->cq = cq` immediately after the CQ is created so
that `oce_mq_free()`'s existing `if (mq->cq != NULL) oce_cq_del(...)`
(oce_queue.c:796-799) handles every error path. See fix.diff.
