# DF-0289 VERDICT: IEEE 802.11 Mesh Route UAF / TOCTOU

## Verdict: REPRODUCED (code-confirmed, not runtime-triggerable)

## Mechanism
`ieee80211_mesh_rt_find()` at ieee80211_mesh.c:230-241 takes `MESH_RT_LOCK`,
looks up a route via `mesh_rt_find_locked()`, then calls `MESH_RT_UNLOCK` at
line 239 BEFORE returning the `rt` pointer:

```c
struct ieee80211_mesh_route *
ieee80211_mesh_rt_find(struct ieee80211vap *vap,
    const uint8_t dest[IEEE80211_ADDR_LEN])
{
    struct ieee80211_mesh_state *ms = vap->iv_mesh;
    struct ieee80211_mesh_route *rt;

    MESH_RT_LOCK(ms);
    rt = mesh_rt_find_locked(ms, dest);
    MESH_RT_UNLOCK(ms);
    return rt;
}
```

The returned `rt` pointer is unreferenced. Callers throughout the file
(lines 1002, 1033, 1043, 1383, 1418, 1441, 1482, 1495, 2009) dereference
`rt->rt_flags`, `rt->rt_nexthop`, etc. WITHOUT holding the lock.

Concurrently, `mesh_rt_del()` (line 354) removes the route from the list
and frees it (`IEEE80211_FREE(rt, M_80211_MESH_RT)` at line 365) while
holding `MESH_RT_LOCK`. The cleanup timer `ms_cleantimer` (lines 850, 869)
can fire at any time and call `mesh_rt_flush` or individual route deletion,
freeing routes that callers of `ieee80211_mesh_rt_find` are still
dereferencing.

Additionally, `ieee80211_mesh_forward_to_gates()` (line 1090) has a
particularly dangerous pattern: inside `TAILQ_FOREACH_SAFE`, it calls
`MESH_RT_UNLOCK(ms)` at line 1146 to transmit frames, then `MESH_RT_LOCK(ms)`
at line 1158. During the unlocked window, the `_SAFE` macro's pre-captured
`next` pointer can be freed by `ms_cleantimer`, causing a UAF on the next
loop iteration.

## Impact
UAF of mesh route / gate structures. A local attacker with WiFi mesh
hardware could trigger route table cleanup concurrent with mesh frame
processing, causing a use-after-free that manifests as a kernel panic (DoS)
or potentially heap corruption. Requires active WiFi mesh networking.

## Not Runtime-Triggerable on This Guest
The guest has no WiFi hardware (only vtnet0 virtio-net). The mesh code
(`ieee80211_mesh_rt_find`) IS compiled into the kernel (present in wlan.ko /
kernel), but creating a mesh VAP requires a WiFi adapter. This is an
"inconclusive: specific HW required" situation.

## Fix
Removed the `MESH_RT_UNLOCK/MESH_RT_LOCK` pair inside the
`TAILQ_FOREACH_SAFE` loop in `forward_to_gates()`, keeping the lock held
for the entire iteration so the `next` cursor cannot be freed. See `fix.diff`.

A complete fix would add reference counting to `struct ieee80211_mesh_route`
so that `ieee80211_mesh_rt_find` returns a referenced route, but that
requires updating all ~10 callers. The targeted fix addresses the most
critical UAF path.

## Kernel Refs
- sys/netproto/802_11/wlan/ieee80211_mesh.c:237-239 — MESH_RT_LOCK/UNLOCK then return rt
- sys/netproto/802_11/wlan/ieee80211_mesh.c:354-366 — mesh_rt_del frees route
- sys/netproto/802_11/wlan/ieee80211_mesh.c:1146 — MESH_RT_UNLOCK inside loop
- sys/netproto/802_11/wlan/ieee80211_mesh.c:1158 — MESH_RT_LOCK re-acquire (UAF window)
