# DF-3288 — ms_known_gates gate entries are never freed: unauthenticated GANN spam grows kernel heap without bound and leaks across vap destroy

File: `sys/netproto/802_11/wlan/ieee80211_mesh.c` (pass 2 audit)

## What

Every accepted GANN action frame from a **new** gate address allocates a
`struct ieee80211_mesh_gate_route` (:2662-2676) and links it into
`ms->ms_known_gates`:

```c
if (found == 0) {
        gr = kmalloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
            M_80211_MESH_GT_RT, M_INTWAIT | M_ZERO);
        IEEE80211_ADDR_COPY(gr->gr_addr, ie.gann_addr);
        TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
}
```

`ms_known_gates` has **no removal path anywhere in sys/** (only
INSERT_TAIL at :907 and :2675; verified by grep), no aging, and
`mesh_vdetach` (:646-659) frees `vap->iv_mesh` without walking the gate
list. Consequences:

1. any mesh peer (established = one beacon + 2 action frames) injects
   GANNs with fresh `gann_addr` values → one ~40-byte kmalloc each,
   forever — **unauthenticated remote kernel memory exhaustion**;
2. destroying the mesh vap leaks the whole table — the entries outlive
   the vap; recreate/destroy cycles accumulate.

(Note: DF-0289 already covers the *gr_route dangling-pointer* aspect of
the gate table; this finding is the *missing free / unbounded growth*,
a different defect at different lines.)

## Reproduced (stock kernel, vmstat -m)

```
# after 500 injected GANNs (sysctl kern.fwm_count=500; kern.fwm_step=20)
80211mesh_gt     503   19.6K       0    390M      503
# after `ifconfig wlan0 destroy`
after vap destroy:
80211mesh_gt     503   19.6K       0    390M      503      <-- LEAKED
# recreate vap, 100 more GANNs, destroy again:
80211mesh_gt     603   23.6K       0    390M      603
80211mesh_gt     603   23.6K       0    390M      603      <-- accumulates forever
```

Meanwhile `80211mesh_rt` returns to 0 on destroy — only the gate table
leaks.

## Build / run

```
sh findings/poc/DF-3286/build.sh    # shared harness
sh findings/poc/DF-3288/run.sh      # 500 GANNs, destroy, vmstat -m
```

## Threat

Remote unauthenticated (post-peering) kernel heap exhaustion; ~40 bytes
per 19-byte action frame, no ceiling, permanent across vap churn.
CWE-401. Severity Medium.
