# DF-4420 VERDICT

**Status: untested (Info-severity leak; PoC exempt per contract — no oce
hardware on the verification guest). Confidence in the bug itself: certain
(every goto path traced below).**

## Path-by-path trace of oce_mq_create (sys/dev/netif/oce/oce_queue.c:662-762)

`cq = oce_cq_create(sc, eq, CQ_LEN_256, sizeof(struct oce_mq_cqe), 1, 1, 0, 0);`
(oce_queue.c:675-678)
  -> on success `cq` owns a DMA ring and is registered in `sc->cq[sc->ncqs++]`
     (oce_queue.c:910 inside oce_cq_create).

| failure after that point | goto path | what oce_mq_free(mq) does | cq freed? |
|---|---|---|---|
| `kmalloc(sizeof(*mq))` NULL (681-685) | `oce_cq_del(sc, cq); goto error;` (683) | mq_free(NULL) returns (779-780) | **YES** |
| `oce_create_ring_buffer` NULL (689-691) | `goto error` (691) -> oce_mq_free(mq) (759) | ring NULL -> skip (782); **mq->cq == NULL -> skip (796)**; kfree(mq) | **NO — leak** |
| `oce_mbox_post`/fw status rc (735-741) | `goto error` (741) -> oce_mq_free(mq) (759) | ring destroyed (782-794); **mq->cq == NULL -> skip (796)**; kfree(mq) | **NO — leak** |

`mq->cq = cq` is only executed on the success path (oce_queue.c:744), which
is why the CQ block in oce_mq_free never fires on the two leaking paths.

Downstream: `sc->mq = oce_mq_create(...)` in oce_queue_init_all
(oce_queue.c:150) receives NULL, `goto error` -> `oce_queue_release_all` —
`sc->mq` is NULL so mq_free is skipped there too (oce_queue.c:189-190). The
leaked `cq` is never referenced again: the only iterators of `sc->cq[]` are
`for_all_cq_queues` (no callers — verified by grep across sys/) and
`oce_hw_update_multicast`-style paths that do not run on this failure path.
No UAF; pure leak.

## Not-testable-on-guest justification

- Guest `uname`: DragonFly dfbsd 6.5-DEVELOPMENT #0 ... X86_64_GENERIC
- `pciconf -lv` / dmesg on the guest: no vendor 0x19a2 (Emulex) device; oce
  driver never attaches, so neither the happy path nor the error path is
  reachable on the verification guest.
- Per the audit contract, Low/Info findings are exempt from mandatory PoC;
  this is filed as Info precisely because the only trigger is a
  firmware/mailbox failure during attach on real hardware.

## Fix validation

fix.diff moves `mq->cq = cq` up to right after the CQ creation so the
existing cleanup in `oce_mq_free` covers all paths (the `!mq` path still
deletes `cq` itself before `mq` exists, so no double-free). Not built on the
guest for the same hardware reason — the change is a one-line pointer
assignment reorder with no control-flow change, reviewed against all four
paths in the table above.

## 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.
