]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtlwifi: validate action frame size in rtl_action_proc()
authorPing-Ke Shih <pkshih@realtek.com>
Tue, 14 Apr 2026 06:22:28 +0000 (14:22 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Wed, 29 Apr 2026 03:00:55 +0000 (11:00 +0800)
Since action frames might be malformed from RX or injected TX, validate
the size before using.

More, use struct ieee80211_mgmt to access fields of action frames instead
of counting barely.

Tested with ping on RTL8723BE. The add BA request action frames of TX/RX
can be handled properly.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260414062229.21047-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtlwifi/base.c

index aad377864e73ba879876cfda8ca847b86cab80bb..9e98c01bb90e6343ac2cd4c367f1d3ffbec00231 100644 (file)
@@ -1369,18 +1369,19 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
        struct ieee80211_hdr *hdr = rtl_get_hdr(skb);
        struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct ieee80211_mgmt *mgmt;
        __le16 fc = rtl_get_fc(skb);
-       u8 *act = (u8 *)(((u8 *)skb->data + MAC80211_3ADDR_LEN));
-       u8 category;
 
        if (!ieee80211_is_action(fc))
                return true;
 
-       category = *act;
-       act++;
-       switch (category) {
+       mgmt = (void *)skb->data;
+       if (skb->len < IEEE80211_MIN_ACTION_SIZE(action_code))
+               return true;
+
+       switch (mgmt->u.action.category) {
        case ACT_CAT_BA:
-               switch (*act) {
+               switch (mgmt->u.action.action_code) {
                case ACT_ADDBAREQ:
                        if (mac->act_scanning)
                                return false;
@@ -1394,9 +1395,11 @@ bool rtl_action_proc(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
                                struct ieee80211_sta *sta = NULL;
                                struct rtl_sta_info *sta_entry = NULL;
                                struct rtl_tid_data *tid_data;
-                               struct ieee80211_mgmt *mgmt = (void *)skb->data;
                                u16 capab = 0, tid = 0;
 
+                               if (skb->len < IEEE80211_MIN_ACTION_SIZE(addba_req))
+                                       return true;
+
                                rcu_read_lock();
                                sta = rtl_find_sta(hw, hdr->addr3);
                                if (sta == NULL) {