]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: free ack status frame on TX header build failure
authorZhiling Zou <roxy520tt@gmail.com>
Fri, 26 Jun 2026 16:58:30 +0000 (00:58 +0800)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 6 Jul 2026 12:11:07 +0000 (14:11 +0200)
ieee80211_build_hdr() stores an ACK status frame before it has
finished all validation and header construction. If a later error path
is taken, the transmit skb is freed but the stored ACK status frame
remains in local->ack_status_frames.

This can happen for control port frames when the requested MLO link ID
does not match the link selected for a non-MLO station. Repeated
failures can fill the ACK status IDR and leave pending ACK frames until
hardware teardown.

Remove any stored ACK status frame before returning an error after it
has been inserted into the IDR.

Fixes: a729cff8ad51 ("mac80211: implement wifi TX status")
Cc: stable@vger.kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Yifan Wu <yifanwucs@gmail.com>
Reported-by: Juefei Pu <tomapufckgml@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zhiling Zou <roxy520tt@gmail.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
Link: https://patch.msgid.link/9de0423da840e92084915b8f92e66a421245c4b8.1782462409.git.roxy520tt@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/tx.c

index c13b209fad47aaac20840db486f82979610b5c75..91b14112e24f086f92fba813228f8e5ac269d9f8 100644 (file)
@@ -2607,6 +2607,18 @@ static u16 ieee80211_store_ack_skb(struct ieee80211_local *local,
        return info_id;
 }
 
+static void ieee80211_remove_ack_skb(struct ieee80211_local *local, u16 info_id)
+{
+       struct sk_buff *ack_skb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&local->ack_status_lock, flags);
+       ack_skb = idr_remove(&local->ack_status_frames, info_id);
+       spin_unlock_irqrestore(&local->ack_status_lock, flags);
+
+       kfree_skb(ack_skb);
+}
+
 /**
  * ieee80211_build_hdr - build 802.11 header in the given frame
  * @sdata: virtual interface to build the header for
@@ -2982,7 +2994,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                if (ieee80211_skb_resize(sdata, skb, head_need, ENCRYPT_DATA)) {
                        ieee80211_free_txskb(&local->hw, skb);
                        skb = NULL;
-                       return ERR_PTR(-ENOMEM);
+                       ret = -ENOMEM;
+                       goto free;
                }
        }
 
@@ -3050,6 +3063,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
 
        return skb;
  free:
+       if (info_id)
+               ieee80211_remove_ack_skb(local, info_id);
        kfree_skb(skb);
        return ERR_PTR(ret);
 }