mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
wifi: rtw88: usb: fix memory leaks on USB write failures
When rtw_usb_write_port() fails to submit a USB Request Block (URB)
(e.g., due to device disconnect or ENOMEM), the completion callback is
never executed.
Currently, the driver ignores the return value of rtw_usb_write_port()
in rtw_usb_write_data() and rtw_usb_tx_agg_skb(). Because these
functions rely on the completion callback to free the socket buffers
(skbs) and the transaction control block (txcb), a submission failure
results in:
1. A memory leak of the allocated skb in rtw_usb_write_data().
2. A memory leak of the txcb structure and all aggregated skbs in
rtw_usb_tx_agg_skb().
Fix this by checking the return value of rtw_usb_write_port(). If it
fails, explicitly free the skb in rtw_usb_write_data(), and properly
purge the tx_ack_queue and free the txcb in rtw_usb_tx_agg_skb().
The issue was discovered in practice during device disconnect/reconnect
scenarios and memory pressure conditions. Tested by verifying normal TX
operation continues after the fix without regressions.
Fixes: a82dfd33d1 ("wifi: rtw88: Add common USB chip support")
Cc: stable@vger.kernel.org
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Tested-by: Luka Gejak <luka.gejak@linux.dev>
Signed-off-by: Luka Gejak <luka.gejak@linux.dev>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260518142311.10328-2-luka.gejak@linux.dev
This commit is contained in:
parent
c80788f7c5
commit
6b964941bb
|
|
@ -399,6 +399,7 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
|
|||
int agg_num = 0;
|
||||
unsigned int align_next = 0;
|
||||
u8 qsel;
|
||||
int ret;
|
||||
|
||||
if (skb_queue_empty(list))
|
||||
return false;
|
||||
|
|
@ -456,7 +457,13 @@ static bool rtw_usb_tx_agg_skb(struct rtw_usb *rtwusb, struct sk_buff_head *list
|
|||
tx_desc = (struct rtw_tx_desc *)skb_head->data;
|
||||
qsel = le32_get_bits(tx_desc->w1, RTW_TX_DESC_W1_QSEL);
|
||||
|
||||
rtw_usb_write_port(rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb);
|
||||
ret = rtw_usb_write_port(rtwdev, qsel, skb_head,
|
||||
rtw_usb_write_port_tx_complete, txcb);
|
||||
if (ret) {
|
||||
ieee80211_purge_tx_queue(rtwdev->hw, &txcb->tx_ack_queue);
|
||||
kfree(txcb);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -518,8 +525,10 @@ static int rtw_usb_write_data(struct rtw_dev *rtwdev,
|
|||
|
||||
ret = rtw_usb_write_port(rtwdev, qsel, skb,
|
||||
rtw_usb_write_port_complete, skb);
|
||||
if (unlikely(ret))
|
||||
if (unlikely(ret)) {
|
||||
rtw_err(rtwdev, "failed to do USB write, ret=%d\n", ret);
|
||||
dev_kfree_skb_any(skb);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user