| From 93fa949641960cab83ea78851b31a757664eebef Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 17 Nov 2025 20:32:59 -0500 |
| Subject: wifi: rtl818x: rtl8187: Fix potential buffer underflow in |
| rtl8187_rx_cb() |
| |
| From: Seungjin Bae <eeodqql09@gmail.com> |
| |
| [ Upstream commit b647d2574e4583c2e3b0ab35568f60c88e910840 ] |
| |
| The rtl8187_rx_cb() calculates the rx descriptor header address |
| by subtracting its size from the skb tail pointer. |
| However, it does not validate if the received packet |
| (skb->len from urb->actual_length) is large enough to contain this |
| header. |
| |
| If a truncated packet is received, this will lead to a buffer |
| underflow, reading memory before the start of the skb data area, |
| and causing a kernel panic. |
| |
| Add length checks for both rtl8187 and rtl8187b descriptor headers |
| before attempting to access them, dropping the packet cleanly if the |
| check fails. |
| |
| Fixes: 6f7853f3cbe4 ("rtl8187: change rtl8187_dev.c to support RTL8187B (part 2)") |
| Signed-off-by: Seungjin Bae <eeodqql09@gmail.com> |
| Signed-off-by: Ping-Ke Shih <pkshih@realtek.com> |
| Link: https://patch.msgid.link/20251118013258.1789949-2-eeodqql09@gmail.com |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../wireless/realtek/rtl818x/rtl8187/dev.c | 27 +++++++++++++------ |
| 1 file changed, 19 insertions(+), 8 deletions(-) |
| |
| diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c |
| index c9df185dc3f4f..00493a2391179 100644 |
| --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c |
| +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c |
| @@ -338,14 +338,16 @@ static void rtl8187_rx_cb(struct urb *urb) |
| spin_unlock_irqrestore(&priv->rx_queue.lock, f); |
| skb_put(skb, urb->actual_length); |
| |
| - if (unlikely(urb->status)) { |
| - dev_kfree_skb_irq(skb); |
| - return; |
| - } |
| + if (unlikely(urb->status)) |
| + goto free_skb; |
| |
| if (!priv->is_rtl8187b) { |
| - struct rtl8187_rx_hdr *hdr = |
| - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); |
| + struct rtl8187_rx_hdr *hdr; |
| + |
| + if (skb->len < sizeof(struct rtl8187_rx_hdr)) |
| + goto free_skb; |
| + |
| + hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); |
| flags = le32_to_cpu(hdr->flags); |
| /* As with the RTL8187B below, the AGC is used to calculate |
| * signal strength. In this case, the scaling |
| @@ -355,8 +357,12 @@ static void rtl8187_rx_cb(struct urb *urb) |
| rx_status.antenna = (hdr->signal >> 7) & 1; |
| rx_status.mactime = le64_to_cpu(hdr->mac_time); |
| } else { |
| - struct rtl8187b_rx_hdr *hdr = |
| - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); |
| + struct rtl8187b_rx_hdr *hdr; |
| + |
| + if (skb->len < sizeof(struct rtl8187b_rx_hdr)) |
| + goto free_skb; |
| + |
| + hdr = (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); |
| /* The Realtek datasheet for the RTL8187B shows that the RX |
| * header contains the following quantities: signal quality, |
| * RSSI, AGC, the received power in dB, and the measured SNR. |
| @@ -409,6 +415,11 @@ static void rtl8187_rx_cb(struct urb *urb) |
| skb_unlink(skb, &priv->rx_queue); |
| dev_kfree_skb_irq(skb); |
| } |
| + return; |
| + |
| +free_skb: |
| + dev_kfree_skb_irq(skb); |
| + return; |
| } |
| |
| static int rtl8187_init_urbs(struct ieee80211_hw *dev) |
| -- |
| 2.51.0 |
| |