[PATCH rtw-next v3 1/3] wifi: rtl8xxxu: free RX skb when URB submission fails
From: Kim Wooseok via B4 Relay
Date: Sat Sep 19 2026 - 16:44:33 EST
From: Kim Wooseok <5mghybrid@xxxxxxxxx>
When usb_submit_urb() fails, rtl8xxxu_submit_rx_urb() unanchors the URB
but leaves the newly allocated skb in urb.context. For ENOMEM/EAGAIN,
the RX worker puts the request back on the pending list. The next
submission allocates another skb and overwrites that pointer, leaking
the previous buffer. Stopping before the retry also leaks it, because
pending-list cleanup frees only the URB.
Free the skb and clear urb.context in rtl8xxxu_submit_rx_urb() when
submission fails. This keeps buffer allocation and failure cleanup in
the same function, so a request returned for retry or teardown no longer
owns an skb. Remove the corresponding cleanup from start and the RX
worker; they only need to decide whether to retry or free the URB.
Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)")
Reviewed-by: Ping-Ke Shih <pkshih@xxxxxxxxxxx>
Assisted-by: GPT-6 Astra
Signed-off-by: Kim Wooseok <5mghybrid@xxxxxxxxx>
---
drivers/net/wireless/realtek/rtl8xxxu/core.c | 16 +++++-----------
1 file changed, 5 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c
index bddbd0990de72..795a5ec2f8cd4 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
@@ -5864,7 +5864,6 @@ static void rtl8xxxu_rx_urb_work(struct work_struct *work)
struct rtl8xxxu_priv *priv;
struct rtl8xxxu_rx_urb *rx_urb, *tmp;
struct list_head local;
- struct sk_buff *skb;
unsigned long flags;
int ret;
@@ -5896,8 +5895,6 @@ static void rtl8xxxu_rx_urb_work(struct work_struct *work)
default:
dev_warn(&priv->udev->dev,
"failed to requeue urb with error %i\n", ret);
- skb = (struct sk_buff *)rx_urb->urb.context;
- dev_kfree_skb(skb);
usb_free_urb(&rx_urb->urb);
}
}
@@ -6596,8 +6593,11 @@ static int rtl8xxxu_submit_rx_urb(struct rtl8xxxu_priv *priv,
skb_size, rtl8xxxu_rx_complete, skb);
usb_anchor_urb(&rx_urb->urb, &priv->rx_anchor);
ret = usb_submit_urb(&rx_urb->urb, GFP_ATOMIC);
- if (ret)
+ if (ret) {
usb_unanchor_urb(&rx_urb->urb);
+ dev_kfree_skb(skb);
+ rx_urb->urb.context = NULL;
+ }
return ret;
}
@@ -7410,7 +7410,6 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw)
struct rtl8xxxu_priv *priv = hw->priv;
struct rtl8xxxu_rx_urb *rx_urb;
struct rtl8xxxu_tx_urb *tx_urb;
- struct sk_buff *skb;
unsigned long flags;
int ret, i;
@@ -7461,13 +7460,8 @@ static int rtl8xxxu_start(struct ieee80211_hw *hw)
rx_urb->hw = hw;
ret = rtl8xxxu_submit_rx_urb(priv, rx_urb);
- if (ret) {
- if (ret != -ENOMEM) {
- skb = (struct sk_buff *)rx_urb->urb.context;
- dev_kfree_skb(skb);
- }
+ if (ret)
rtl8xxxu_queue_rx_urb(priv, rx_urb);
- }
}
schedule_delayed_work(&priv->ra_watchdog, 2 * HZ);
--
2.53.0