diff options
| author | Zhao Li <enderaoelyther@gmail.com> | 2026-05-09 12:34:28 +0800 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2026-05-20 11:19:53 +0200 |
| commit | d71c841be5d9e586ee7f36c0dc8ed4db0d9a1349 (patch) | |
| tree | e675b041389a8d9176e4750ced7dab182fff294d /net/mac80211/rx.c | |
| parent | fe2d61a5d2849ee75dd4deeb2fe35f78d80721f8 (diff) | |
| download | linux-next-d71c841be5d9e586ee7f36c0dc8ed4db0d9a1349.tar.gz linux-next-d71c841be5d9e586ee7f36c0dc8ed4db0d9a1349.zip | |
wifi: mac80211: capture fast-RX rate before mesh reuses skb->cb
ieee80211_invoke_fast_rx() reads RX status through
IEEE80211_SKB_RXCB(skb), which aliases the same skb->cb storage
that ieee80211_rx_mesh_data() reuses as IEEE80211_TX_INFO. In the
unicast forward path, mesh_data does:
info = IEEE80211_SKB_CB(fwd_skb);
memset(info, 0, sizeof(*info));
on the same skb the caller still names via rx->skb, then either
queues the skb for TX (success) or kfree_skb()'s it (no-route)
before returning RX_QUEUED. The caller's RX_QUEUED arm then
calls sta_stats_encode_rate(status) on memory that is either
zeroed (success path) or freed (no-route path). The latter is
KASAN slab-use-after-free in ieee80211_prepare_and_rx_handle.
Fix by encoding the rate from status before invoking
ieee80211_rx_mesh_data(), so the RX_QUEUED arm consumes a value
captured while status was still backed by valid memory.
Fixes: 3468e1e0c639 ("wifi: mac80211: add mesh fast-rx support")
Cc: stable@vger.kernel.org
Signed-off-by: Zhao Li <enderaoelyther@gmail.com>
Link: https://patch.msgid.link/20260509043427.60322-2-enderaoelyther@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/rx.c')
| -rw-r--r-- | net/mac80211/rx.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d18e962126ce..3fb40449c6c5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -4984,6 +4984,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, u8 sa[ETH_ALEN]; } addrs __aligned(2); struct ieee80211_sta_rx_stats *stats; + u32 encoded_rate; /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write * to a common data structure; drivers can implement that per queue @@ -5091,11 +5092,14 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, /* push the addresses in front */ memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs)); + /* capture before mesh forward may memset or free skb->cb */ + encoded_rate = sta_stats_encode_rate(status); + res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); switch (res) { case RX_QUEUED: stats->last_rx = jiffies; - stats->last_rate = sta_stats_encode_rate(status); + stats->last_rate = encoded_rate; return true; case RX_CONTINUE: break; |
