]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
ramips: reject invalid frame engine RX lengths 24268/head
authorNickolay Savchenko <n.savchenko@axioma.lv>
Fri, 17 Jul 2026 13:13:05 +0000 (16:13 +0300)
committerJonas Jelonek <jelonek.jonas@gmail.com>
Mon, 20 Jul 2026 13:48:26 +0000 (15:48 +0200)
fe_poll_rx() takes the packet length directly from the RX descriptor and
passes it to skb_put() without checking that it fits in the allocated
buffer.  A malformed or stale descriptor can therefore extend the skb
beyond its tailroom and corrupt memory.

Reject lengths larger than skb_tailroom(), account the packet in
rx_length_errors and rx_dropped, free the affected skb, and continue by
installing the replacement descriptor.

Signed-off-by: Nickolay Savchenko <n.savchenko@axioma.lv>
Link: https://github.com/openwrt/openwrt/pull/24268
Signed-off-by: Jonas Jelonek <jelonek.jonas@gmail.com>
target/linux/ramips/files/drivers/net/ethernet/ralink/mtk_eth_soc.c

index a7b421ceb5123d648d3efa430e38bd6f04eed44e..ad4658926872dbbce9ca499e33b279a667a211da 100644 (file)
@@ -970,6 +970,16 @@ static int fe_poll_rx(struct napi_struct *napi, int budget,
                                 ring->rx_buf_size, DMA_FROM_DEVICE);
                pktlen = RX_DMA_GET_PLEN0(trxd.rxd2);
                skb->dev = netdev;
+               if (unlikely(pktlen > skb_tailroom(skb))) {
+                       if (net_ratelimit())
+                               netdev_warn(netdev,
+                                           "dropping invalid RX length %u (buffer %u, descriptor %08x)\n",
+                                           pktlen, skb_tailroom(skb), trxd.rxd2);
+                       stats->rx_length_errors++;
+                       stats->rx_dropped++;
+                       dev_kfree_skb_any(skb);
+                       goto replace_desc;
+               }
                skb_put(skb, pktlen);
                if (trxd.rxd4 & checksum_bit)
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -987,6 +997,7 @@ static int fe_poll_rx(struct napi_struct *napi, int budget,
 
                napi_gro_receive(napi, skb);
 
+replace_desc:
                ring->rx_data[idx] = new_data;
                rxd->rxd1 = (unsigned int)dma_addr;