UAF/TOCTOU: mesh route pointers returned unreferenced, forward_to_gates drops lock mid-traversal
Summary
ieee80211_mesh_rt_find(:230-241) returns rt after MESH_RT_UNLOCK no refcount. Callers deref rt->rt_flags/rt_nexthop unlocked. ms_cleantimer callout can free route concurrently. forward_to_gates(:1146) MESH_RT_UNLOCK then re-LOCK inside TAILQ_FOREACH_SAFE β next cursor can be freed. UAF of mesh route/gate struct.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0289 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | Remove MESH_RT_UNLOCK/LOCK inside forward_to_gates TAILQ_FOREACH_SAFE loop | 1.0 KB | view raw |
| VERDICT.md | verdict | Full analysis of mesh route UAF | 3.0 KB | β raw |
| README.md | readme | Finding summary and reproduction notes | 1.0 KB | β raw |
| build.sh | build-script | Verify mesh code present in kernel | 332 B | view raw |
| run.sh | run-script | Verify UAF code path in source | 650 B | view raw |
| env.txt | environment | Guest environment | 442 B | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-0289: WiFi Mesh Route UAF / TOCTOU
Finding
ieee80211_mesh_rt_find() (ieee80211_mesh.c:230-241) returns a route pointer
after releasing MESH_RT_LOCK. Callers dereference rt->rt_flags/rt_nexthop
unlocked. ms_cleantimer can free routes concurrently. forward_to_gates()
drops/reacquires the lock inside TAILQ_FOREACH_SAFE, allowing the next cursor
to be freed β UAF of mesh route/gate struct.
Reproduction
This is a code-confirmed finding. Runtime reproduction requires WiFi mesh hardware (802.11s), which is not present on this QEMU guest (vtnet0 only).
The mesh code IS compiled into the kernel:
nm /boot/kernel/kernel | grep ieee80211_mesh_rt_find
To reproduce on hardware with WiFi mesh: 1. Create a mesh VAP (wlan0 mesh mode) 2. Generate mesh traffic + route churn 3. Observe UAF panic in dmesg during forward_to_gates or route lookup
Fix
See fix.diff β removes the MESH_RT_UNLOCK/LOCK pair inside forward_to_gates's TAILQ_FOREACH_SAFE loop, keeping the lock held for the entire iteration.
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:
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)
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. mesh_rt_find returns unreferenced rt pointer, forward_to_gates drops lock during iteration -> UAF. No WiFi HW.
No comments yet.