]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtl818x: rtl8187: Fix potential buffer underflow in rtl8187_rx_cb()
authorSeungjin Bae <eeodqql09@gmail.com>
Tue, 18 Nov 2025 01:32:59 +0000 (20:32 -0500)
committerPing-Ke Shih <pkshih@realtek.com>
Fri, 21 Nov 2025 03:38:20 +0000 (11:38 +0800)
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
drivers/net/wireless/realtek/rtl818x/rtl8187/dev.c

index 0c5c66401daa6daa08b621c8c9d4c640b0e307de..7aa2da0cd63cc826455e6ea3d37daca5903911fa 100644 (file)
@@ -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)