[PATCH wireless-next 1/4] wifi: mac80211: fix unauthorised port check for encap offload
Johannes Berg <[email protected]> Sun, 2 Aug 2026 10:57:18 +0200
| Newsgroups | org.kernel.vger.linux-wireless |
|---|---|
| Message-ID | <20260802105818.dd5da579813d.I51ed0121154bb652bebc97bb0597b1fae9ac978f@changeid> |
From: Johannes Berg <[email protected]> The check in ieee80211_tx_dequeue() reads frame_control, addr1 and addr2 out of the skb, but for encapsulation offload that's just a random part of the ethernet addresses, so dropping depends on bits in the destination address. This is obviously wrong. Refactor the check and short-circuit for ethernet format frames, it only needs the port-control flag check since those are locally generated and not forwarded frames. Fixes: 50ff477a8639 ("mac80211: add 802.11 encapsulation offloading support") Signed-off-by: Johannes Berg <[email protected]> --- net/mac80211/tx.c | 48 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0cf5f6ec75e6..44c40c98b497 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3882,6 +3882,38 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata, return true; } +static bool ieee80211_drop_unauth_port(struct ieee80211_tx_data *tx) +{ + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb); + struct ieee80211_hdr *hdr; + + if (likely(test_sta_flag(tx->sta, WLAN_STA_AUTHORIZED))) + return false; + + if (info->flags & IEEE80211_TX_CTL_INJECTED) + return false; + + if (ieee80211_vif_is_mesh(&tx->sdata->vif) || + tx->sdata->vif.type == NL80211_IFTYPE_OCB) + return false; + + /* no need to check forwarding here */ + if (info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP) + return !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO); + + hdr = (struct ieee80211_hdr *)tx->skb->data; + + if (!ieee80211_is_data_present(hdr->frame_control) || + is_multicast_ether_addr(hdr->addr1)) + return false; + + if ((info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO) && + ieee80211_is_our_addr(tx->sdata, hdr->addr2, NULL)) + return false; + + return true; +} + struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, struct ieee80211_txq *txq) { @@ -3948,20 +3980,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, if (txq->sta) { tx.sta = container_of(txq->sta, struct sta_info, sta); - /* - * Drop unicast frames to unauthorised stations unless they are - * injected frames or EAPOL frames from the local station. - */ - if (unlikely(!(info->flags & IEEE80211_TX_CTL_INJECTED) && - ieee80211_is_data_present(hdr->frame_control) && - !ieee80211_vif_is_mesh(&tx.sdata->vif) && - tx.sdata->vif.type != NL80211_IFTYPE_OCB && - !is_multicast_ether_addr(hdr->addr1) && - !test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) && - (!(info->control.flags & - IEEE80211_TX_CTRL_PORT_CTRL_PROTO) || - !ieee80211_is_our_addr(tx.sdata, hdr->addr2, - NULL)))) { + + if (unlikely(ieee80211_drop_unauth_port(&tx))) { I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); ieee80211_free_txskb(&local->hw, skb); goto begin; -- 2.55.0