[PATCH wireless-next 2/4] wifi: mac80211: fix key selection for encap offload frames
Johannes Berg <[email protected]> Sun, 2 Aug 2026 10:57:19 +0200
| Newsgroups | org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <20260802105818.0feb7ad61047.Ia506ca211176a3c466bc60e4cc3e506df34a4a67@changeid> |
From: Johannes Berg <[email protected]> ieee80211_tx_h_select_key() assumes the frame is in 802.11 format for picking the key, at least when there's no pairwise TK for the STA to transmit with. For unicast this is likely not relevant because if there's no pairwise TK for the STA there's probably not going to be any other key either. But multicast encapsulation offload frames have no STA, so it looks at the ethernet header as if it was 802.11. This may not matter very much since multicast encapsulation offload is likely to ignore the key selection, but it's still wrong. Create a separate selection function that doesn't (need to) look at the frame header - it's data anyway, so either unicast to a station (with sta pointer) or multicast. For MLO, the driver has to duplicate the frame and select the key anyway, so just skip it in that case entirely. Fixes: 50ff477a8639 ("mac80211: add 802.11 encapsulation offloading support") Signed-off-by: Johannes Berg <[email protected]> --- net/mac80211/tx.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 44c40c98b497..2ef77bb80b92 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -592,6 +592,34 @@ ieee80211_select_link_key(struct ieee80211_tx_data *tx) return NULL; } +/* + * An 802.3 frame is always a data frame, so there are no 802.11 addresses to + * look at: with a station the pairwise key is all that can apply, without one + * the frame is group addressed. On an MLD the driver has to pick the group key + * itself, as the same frame goes out on several links that each have their own. + */ +static ieee80211_tx_result +ieee80211_select_key_8023(struct ieee80211_tx_data *tx) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + + if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) + return TX_CONTINUE; + + if (tx->sta) { + tx->key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx]); + if (!tx->key) + tx->key = rcu_dereference(tx->sdata->default_unicast_key); + } else if (!ieee80211_vif_is_mld(&tx->sdata->vif)) { + tx->key = rcu_dereference(tx->sdata->deflink.default_multicast_key); + } + + if (tx->key && tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) + info->control.hw_key = &tx->key->conf; + + return TX_CONTINUE; +} + static ieee80211_tx_result debug_noinline ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) { @@ -599,6 +627,9 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; + if (info->control.flags & IEEE80211_TX_CTL_HW_80211_ENCAP) + return ieee80211_select_key_8023(tx); + if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) { tx->key = NULL; return TX_CONTINUE; @@ -615,12 +646,6 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) else tx->key = NULL; - if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) { - if (tx->key && tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) - info->control.hw_key = &tx->key->conf; - return TX_CONTINUE; - } - if (tx->key) { bool skip_hw = false; -- 2.55.0