# DF-4079 — oce_rx: CQE pkt_size vs num_fragments×frag_size desync builds an
# inconsistent mbuf chain (m_pkthdr.len > Σ m_len) handed to the network stack

File: sys/dev/netif/oce/oce_if.c (pass 2)
Class: memory-safety contract violation → stack offset-walker panic
(`m_copydata` KASSERT) / TCP sequence desync
VERIFIED: reproduced (baseline + panic) on the DFly QEMU guest via the
production-handler KLD dispatch rig; fix validated on a rebuilt kernel.

## How it was verified without OneConnect hardware

The guest kernel is built with `device oce` (X86_64_GENERIC), so the driver's
production code — including the static `oce_rx()` — lives in the RUNNING
kernel image. The KLD rig (`df4079_oce_poc.c`):

- references the kernel's own `oce_rq_handler()`, `oce_alloc_rx_bufs()`,
  `oce_create_ring_buffer()`, `oce_destroy_ring_buffer()` and
  `oce_free_posted_rxbuf()` as extern symbols (kernel-loader bound —
  nothing recompiled);
- fabricates the post-attach softc exactly as production leaves it (BE3
  flags, frag_size 2048, verbatim `oce_rq_init` DMA replay, real busdma
  rings from the kernel's own ring allocator, MMIO BAR stand-in pages);
- posts real RX clusters via the REAL `oce_alloc_rx_bufs()`;
- crafts the CQE bitfields the way firmware DMA-writes them:
  `pkt_size=16383, num_fragments=1` and `pkt_size=16383, num_fragments=7`;
- dispatches the REAL `oce_rq_handler(rq)` (static `oce_rx` runs inside);
- captures the delivered chain in an if_input shim and prints
  claimed (m_pkthdr.len) vs actual (Σ m_len).

## Results (stock kernel #0 Thu Jul 2 06:02:54 UTC 2026)

- case 1 (pkt_size=16383, nf=1): chain 2048 bytes, claims 16383 →
  **14335 phantom bytes**
- case 2 (pkt_size=16383, nf=7): chain 7×2048=14336 bytes, claims 16383 →
  **2047 phantom bytes** (the finding's headline gap)
- panic mode: the real stack offset-walker `m_copydata(m, off=2056, 8)` —
  the exact consumer cited (sys/kern/uipc_mbuf.c:1679, kernel built with
  INVARIANTS) — panics:
  `panic: m_copydata: offset > size of mbuf chain`
  with backtrace `m_copydata() ← df4079_input() ← oce_rx.isra.10() ←
  oce_rq_handler()` — production `oce_rx` built the chain, production
  `m_copydata` died on it.

## Fix validation (fix.diff, fix_build.log, fix_run.log)

`fix.diff` adds the residual-length check to `oce_rx`: if `len != 0` after
the fragment loop, the chain is freed and dropped. Applied to the guest's
/usr/src (identical to the audit tree), kernel rebuilt
(`make -j6 nativekernel KERNCONF=X86_64_GENERIC`) and installed, booted
into `#1: Thu Oct 15 13:06:11 UTC 2026`. The SAME rig re-run against the
patched kernel's own `oce_rq_handler` (address re-resolved at module load):
both crafted CQEs dropped — `chains delivered to if_input: 0; invariant
violations: 0; rx_pkts=0` → **FIX CONFIRMED**; panic mode on the patched
kernel SURVIVES (no chain → no `m_copydata` dispatch → no panic).

## Reproduce

```
vm.sh run_root 'sh /root/df4079/build.sh'    # build the KLD
vm.sh run_root 'sh /root/df4079/run.sh baseline'   # survives, prints violations
vm.sh reset with-src                          # fresh boot for the panic run
vm.sh run_root 'sh /root/df4079/run.sh panic'      # kernel panic
```

Threat model unchanged from the finding: pkt_size/num_fragments are
firmware/DMA-controlled; the driver must not trust the completion.
