[PATCH RESEND wireless 1/4] wifi: rtl8xxxu: free RX skb when URB submission fails
From: kimwooseok
Date: Sat Sep 12 2026 - 18:09:43 EST
A failed RX URB submission can leak the skb allocated for that attempt.
rtl8xxxu_submit_rx_urb() allocates the buffer and stores it in urb.context,
but if usb_submit_urb() fails, it only unanchors the URB. The RX worker
queues ENOMEM/EAGAIN failures for retry with that buffer still attached.
On the next attempt, rtl8xxxu_submit_rx_urb() allocates another skb and
overwrites urb.context, losing the reference to the previous buffer.
Stopping before the retry also leaks the buffer because pending-request
cleanup frees only the URB.
Fix the leak at the submission failure by making rtl8xxxu_submit_rx_urb()
responsible for both allocating the skb and releasing it when submission
fails. Free the newly allocated skb and clear urb.context before returning
the error, so neither retry nor stop receives a pending URB that still
owns a buffer. Remove the caller-side skb cleanup from start and the RX
worker; those callers now handle only whether to retry or release the URB.
Fixes: 26f1fad29ad9 ("New driver: rtl8xxxu (mac80211)")
Assisted-by: GPT-6 Astra
Signed-off-by: kimwooseok <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.48.1