Skip to contentSkip to conversation

wifi: mac80211: free ack status frame on TX header build failure

PATCH New Ren Wei 1 participant 1 message Jun 26 1 message not in the archive mac80211

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

Ren Wei

author
#1 lore raw

PATCH 1/1 wifi: mac80211: free ack status frame on TX header build failure

From: Zhiling Zou <[email protected]>

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")
Assisted-by Codex:gpt-5.4
---
 net/mac80211/tx.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
net/mac80211/tx.c +16 -1
index ea7f63e1fc17..8e7f43ee10e5 100644
@@ -2597,6 +2597,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
@@ -2972,7 +2984,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;
 		}
 	}
 
@@ -3040,6 +3053,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);
 }
Signature · 1 line
2.43.0