# DF-3333 — VERDICT

**Finding:** escalation of the DF-0359 ring-state corruption into an
out-of-bounds slot access and OOB *write* in `netmap_transmit()`.

## Reproduced? YES — in a real kernel, with the verbatim functions.

Constraint (same as DF-3332): the netmap subsystem does not compile on this
DragonFly tree (`netmap_kern.h:747` / `ifnet.if_unused7` removed; no
sys/conf/files entry; no netmap.ko).  The two vulnerable functions —
`netmap_rxsync_from_host()` (netmap.c:884-929) and the `netmap_transmit()`
insert block (netmap.c:2011-2044) — plus `nm_kr_rxpos()`
(netmap_kern.h:540-556) depend on none of the rotted machinery, so they run
**verbatim** in a KLD (`df3333_kmod.c`, stubs documented in-file; the only
additions are marked INSTRUMENTATION) against a fake pool of
`[ ring | 1024 real slots | 1024 marker slots ]`.

### Run 1 — vulnerable variant (dmesg.txt / run.log)

The choreography replays, ~4.19M times, exactly what an mmap()ed userspace
thread can write before each `NIOCRXSYNC` on the host ring:

    ring->reserved = 0xffffffff;  ring->avail = 1;   /* resvd+avail wraps to 0,
                                                        passes the >= lim+1 guard
                                                        (netmap.c:910) */
    ring->cur = 1023 (then 0 alternating);

Result (dmesg):

    df3333: choreography start (target hwcur>lim with hwavail<lim)
    df3333: after 4194302 pairs: hwcur=2048 hwavail=0 (0x0)  <-- hwcur OUT OF RANGE
    df3333: transmit used slot index 1024 (lim = 1023)  <-- OUT OF BOUNDS
    df3333: RESULT OOB WRITE CONFIRMED at slot[1024] (1 slots past end of ring)  [VULNERABLE]

The `slot->len = 60; slot->flags = 1` writes of netmap.c:2037-2038 landed in
the marker region — **past the end of the slot array** — proving the OOB
write, exactly at the index derived in the analysis (the reachable sum
`hwcur+hwavail` is ≡ 0 mod num_slots, so the first OOB index is 1024).

### Run 2 — FIXED variant (`-DDD3333_FIXED`: second `pos %= num_slots` in
nm_kr_rxpos — the netmap_kern.h part of fix.diff) (run.fixed.log)

    df3333: transmit used slot index 0 (lim = 1023)
    df3333: RESULT no write past ring end (pos=0)  [FIXED]

(The ring corruption itself — hwcur=2048 — remains; that is DF-0359's bug,
addressed by the netmap.c part of fix.diff, the overflow-proof resvd guard.)

## Impact assessment (why Low)

* The OOB write lands **inside the shared netmap memory pool** (the ring
  object is followed by other pool objects/slack; netmap_mem2.c packs rings
  into clusters).  The whole pool is RW-mapped to the netmap clients, so on
  its own this write crosses no privilege boundary — the attacking user
  could write the same bytes directly through their own mapping.
* The security meaning is **cross-client corruption**: the pool is the
  *global* allocator shared by all netmap fds system-wide
  (netmap_get_memory_locked → &nm_mem), so client A (wheel) can corrupt
  client B's ring header/slot/buffer state — including buffer indices
  (`buf_idx` values copied by netmap_sw_to_nic / read by other clients'
  syncs), which chains into DF-0547's cross-adapter double-free/aliasing.
* Practically gated by /dev/netmap permissions (0660 root:wheel on this
  vintage) and — on this tree — by the subsystem not compiling at all.

## Exploit chain (steps, not carried to uid0)

1. NIOCREGIF host ring + mmap (wheel group);
2. NIOCRXSYNC×~8.4M with reserved=0xffffffff/avail=1 lie → hwcur=2048,
   hwavail=0 (underflowed from DF-0359's arithmetic);
3. host stack sends any packet via the interface → netmap_transmit writes
   len/flags at slot[1024] — one slot past the victim ring.

## Kernel references

* sys/net/netmap/netmap.c:909-914 — overflowable resvd+avail guard
* sys/net/netmap/netmap.c:916-921 — hwcur stored out of range, hwavail underflow
* sys/net/netmap/netmap_kern.h:541-545 — nm_kr_rxpos single subtract
* sys/net/netmap/netmap.c:2034-2038 — OOB slot index → OOB len/flags write

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