# DF-0402 — netmap_bdg_learning direct kernel deref of user-controlled pointer

## Bug (certain by inspection)
`sys/net/netmap/netmap_vale.c:994` (`nm_bdg_preflush`) — `NS_INDIRECT` slot:
```c
buf = ft[ft_i].ft_buf = (slot->flags & NS_INDIRECT) ?
    (void *)(uintptr_t)slot->ptr : BDG_NMB(&na->up, slot);
```
`slot->ptr` is a raw user-controlled 64-bit pointer taken verbatim into
`ft_buf`. `sys/net/netmap/netmap_vale.c:1107-1108` (`netmap_bdg_learning`)
then dereferences it directly:
```c
dmac = le64toh(*(uint64_t *)(buf)) & 0xffffffffffff;
smac = le64toh(*(uint64_t *)(buf + 4));
```
There is a later `copyin(src, dst, len)` for the same `NS_INDIRECT` case at
`:1338-1339` (second pass) — the first pass simply skips the copyin.

Impact:
* SMAP-on: supervisor reads a user page → page fault in kernel mode → panic.
* SMAP-off (this audit guest): the deref silently succeeds. If the attacker
  passes a kernel address, the kernel reads 14 bytes of kernel memory and
  uses them for the bridge's MAC-learning hash table — a kernel-memory
  side-channel leak.

## Reach — NOT reachable on the default guest
The netmap subsystem is not part of the default DragonFlyBSD installation:

* `/dev/netmap` does not exist
* `/boot/kernel/netmap.ko` and `/boot/kernel/if_netmap.ko` do not exist
* `kldload if_netmap` / `kldload netmap` → "can't load: file not found"
* `sys/conf/files` has no netmap entries; `sys/config/X86_64_GENERIC` does
  not reference netmap
* `sys/net/netmap/Makefile` exists (kmod), so netmap is *intended* to be
  buildable as a module, BUT attempting to build it against this kernel
  fails immediately:
  ```
  dragonfly/net/netmap/netmap_kern.h:747:27: error: 'struct ifnet' has no
  member named 'if_unused7'; did you mean 'if_unused2'?
  ```
  The netmap source tree has drifted out of sync with the rest of the
  kernel — the sink is effectively dead code in the current tree.

This is the "Genuinely not reachable on this kernel" case: the vulnerable
code does not compile into the kernel, has no loadable module shipped, and
cannot even be built against the current `struct ifnet`. The bug remains a
real defect in the netmap source and would become live again the moment
netmap is repaired and loaded — `fix.diff` is provided for that eventuality.

## Build / Run
No PoC can run on this guest (no netmap, no `/dev/netmap`). The trigger
would be: open `/dev/netmap`, set up a VALE bridge, queue a packet with
`NS_INDIRECT` and a crafted `slot->ptr`, fire TX → kernel deref of the
controlled pointer.

## Fix
`fix.diff`: in `netmap_bdg_learning`, stage the 14 header bytes via
`copyin()` into a stack local (falling back to `bcopy()` if `copyin`
returns EFAULT, i.e. for kernel-address `buf`s from the non-`NS_INDIRECT`
path). Mirrors the existing `copyin` pattern in the second pass at `:1338`.
