[PATCH net v2] net: usb: rtl8150: free skb on usb_submit_urb() failure in xmit

From: Morduan Zang

Date: Thu Apr 23 2026 - 21:57:10 EST


When rtl8150_start_xmit() fails to submit the tx URB, the URB is never
handed to the USB core and write_bulk_callback() will not run. The
driver returns NETDEV_TX_OK, which tells the networking stack that the
skb has been consumed, but nothing actually frees the skb on this
error path:

dev->tx_skb = skb;
...
if ((res = usb_submit_urb(dev->tx_urb, GFP_ATOMIC))) {
...
/* no kfree_skb here */
}
return NETDEV_TX_OK;

This leaks the skb on every submit failure and also leaves dev->tx_skb
pointing at memory that the driver itself may later free, which is
fragile.

Free the skb with dev_kfree_skb_any() in the error path and clear
dev->tx_skb so no stale pointer is left behind.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reviewed-by: Andrew Lunn <andrew@xxxxxxx>
Signed-off-by: Morduan Zang <zhangdandan@xxxxxxxxxxxxx>
---
Changes in v2:
- Rebase on net/main as requested (Jakub Kicinski). v1 was based on
a tree that also carried the pending UAF fix ("net: usb: rtl8150:
fix use-after-free in rtl8150_start_xmit()"), so v1 did not apply
on net/main. v2 is an independent fix that applies cleanly to
net/main on its own; it does not depend on the UAF fix being
applied first.
- No code change besides the rebase context.

v1: https://lore.kernel.org/all/678BC10BB9E39322+20260421111025.15833-1-zhangdandan@xxxxxxxxxxxxx/
---
drivers/net/usb/rtl8150.c | 7 +++++++
1 file changed, 7 insertions(+)

diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 4cda0643afb6..9999484d2c5e 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -707,6 +707,13 @@ static netdev_tx_t rtl8150_start_xmit(struct sk_buff *skb,
netdev->stats.tx_errors++;
netif_start_queue(netdev);
}
+ /*
+ * The URB was not submitted, so write_bulk_callback() will
+ * never run to free dev->tx_skb. Drop the skb here and
+ * clear tx_skb to avoid leaving a stale pointer.
+ */
+ dev->tx_skb = NULL;
+ dev_kfree_skb_any(skb);
} else {
netdev->stats.tx_packets++;
netdev->stats.tx_bytes += skb->len;
--
2.50.1