[PATCH wireless 1/1] wifi: mac80211: fix mesh fast xmit path deletion UAF

From: Zihan Xi

Date: Tue Sep 08 2026 - 02:29:19 EST


mesh_fast_tx_cache() stores raw mesh_path pointers in a persistent
fast-xmit cache entry. Path deletion flushes currently visible cache
entries and then schedules the path for RCU freeing, but a sender that
already holds the path in an RCU read-side section can insert a new
entry after that flush. Once the lookup RCU section ends, the path is
freed while the new cache entry still points at it. A later
mesh_fast_tx_get() then dereferences the freed flags, expiry, or
next_hop fields.

Mark the path MESH_PATH_DELETED before flushing the cache, and reject
cache insertion if the mesh path or optional MPP path was deleted while
the entry was being built. The cache walk lock orders this check with
deletion flush, so entries inserted before the flush are removed and
later entries are not cached.

The crash path is ieee80211_mesh_xmit_fast() -> mesh_fast_tx_get().
The same cache is also consumed by ieee80211_rx_mesh_fast_forward(),
so the deletion tombstone covers both consumers.

Fixes: d5edb9ae8d56 ("wifi: mac80211: mesh fast xmit support")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Vega <vega@xxxxxxxxxx>
Assisted-by: LLM
Co-developed-by: Luxing Yin <root@xxxxxxxxxx>
Signed-off-by: Luxing Yin <root@xxxxxxxxxx>
Signed-off-by: Zihan Xi <zihanx@xxxxxxxxxx>
---
net/mac80211/mesh_pathtbl.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index 03171cf008557..dfcc4f3a7088e 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -577,6 +577,12 @@ void mesh_fast_tx_cache(struct ieee80211_sub_if_data *sdata,
goto unlock_sta;

spin_lock(&cache->walk_lock);
+ if ((READ_ONCE(mpath->flags) & MESH_PATH_DELETED) ||
+ (mppath && (READ_ONCE(mppath->flags) & MESH_PATH_DELETED))) {
+ kfree(entry);
+ goto unlock_cache;
+ }
+
prev = rhashtable_lookup_get_insert_fast(&cache->rht,
&entry->rhash,
fast_tx_rht_params);
@@ -812,6 +818,9 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath)
{
hlist_del_rcu(&mpath->walk_list);
rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
+ spin_lock_bh(&mpath->state_lock);
+ mpath->flags |= MESH_PATH_DELETED;
+ spin_unlock_bh(&mpath->state_lock);
if (tbl == &mpath->sdata->u.mesh.mpp_paths)
mesh_fast_tx_flush_addr(mpath->sdata, mpath->dst);
else
--
2.43.0