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>
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;
napi_gro_receive(napi, skb);
+replace_desc:
ring->rx_data[idx] = new_data;
rxd->rxd1 = (unsigned int)dma_addr;