[SRU][J][PATCH 1/1] net: mvpp2: refill RX buffers before XDP or skb use
Cengiz Can
cengiz.can at canonical.com
Wed Jul 15 11:16:24 UTC 2026
From: Til Kaiser <mail at tk154.de>
The RX error path returns the current descriptor buffer to the hardware
BM pool. That is only valid while the driver still owns the buffer.
mvpp2_rx_refill() can fail after the current buffer has been handed to
XDP or attached to an skb. In those cases mvpp2_run_xdp() may have
recycled, redirected, or queued the page for XDP_TX, and an skb free also
retires the data buffer. Returning such a buffer to BM lets hardware DMA
into memory that is no longer owned by the RX ring.
Refill the BM pool before handing the current buffer to XDP or to the
skb. If the allocation fails there, drop the packet and return the
still-owned current buffer to BM, preserving the pool depth. Once the
refill succeeds, later local drops retire/free the current buffer instead
of returning it to BM.
Fixes: 07dd0a7aae7f ("mvpp2: add basic XDP support")
Fixes: d6526926de73 ("net: mvpp2: fix memory leak in mvpp2_rx")
Signed-off-by: Til Kaiser <mail at tk154.de>
Link: https://patch.msgid.link/20260607134943.21996-4-mail@tk154.de
Signed-off-by: Paolo Abeni <pabeni at redhat.com>
(cherry picked from commit 5e8e2a9624df72fca7c736b2966b2cbf6c9c3ff6)
CVE-2026-53215
Assisted-by: kybele:claude-opus-4.8
Signed-off-by: Cengiz Can <cengiz.can at canonical.com>
---
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 43 +++++++++++--------
1 file changed, 24 insertions(+), 19 deletions(-)
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index fdfdd55fdb1d..31a2078a77ae 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3969,6 +3969,12 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
else
frag_size = bm_pool->frag_size;
+ err = mvpp2_rx_refill(port, bm_pool, pp, pool);
+ if (err) {
+ netdev_err(port->dev, "failed to refill BM pools\n");
+ goto err_drop_frame;
+ }
+
if (xdp_prog) {
struct xdp_rxq_info *xdp_rxq;
@@ -3986,12 +3992,6 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
if (ret) {
xdp_ret |= ret;
- err = mvpp2_rx_refill(port, bm_pool, pp, pool);
- if (err) {
- netdev_err(port->dev, "failed to refill BM pools\n");
- goto err_drop_frame;
- }
-
ps.rx_packets++;
ps.rx_bytes += rx_bytes;
continue;
@@ -4001,8 +4001,21 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
skb = build_skb(data, frag_size);
if (!skb) {
netdev_warn(port->dev, "skb build failed\n");
- goto err_drop_frame;
+ if (pp) {
+ page_pool_put_page(pp, virt_to_head_page(data),
+ rx_bytes + MVPP2_MH_SIZE,
+ true);
+ } else {
+ dma_unmap_single_attrs(dev->dev.parent, dma_addr,
+ bm_pool->buf_size,
+ DMA_FROM_DEVICE,
+ DMA_ATTR_SKIP_CPU_SYNC);
+ mvpp2_frag_free(bm_pool, pp, data);
+ }
+ goto err_drop_frame_retired;
}
+ if (pp)
+ skb_mark_for_recycle(skb);
/* If we have RX hardware timestamping enabled, grab the
* timestamp from the queue and convert.
@@ -4013,16 +4026,7 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
skb_hwtstamps(skb));
}
- err = mvpp2_rx_refill(port, bm_pool, pp, pool);
- if (err) {
- netdev_err(port->dev, "failed to refill BM pools\n");
- dev_kfree_skb_any(skb);
- goto err_drop_frame;
- }
-
- if (pp)
- skb_mark_for_recycle(skb);
- else
+ if (!pp)
dma_unmap_single_attrs(dev->dev.parent, dma_addr,
bm_pool->buf_size, DMA_FROM_DEVICE,
DMA_ATTR_SKIP_CPU_SYNC);
@@ -4039,13 +4043,14 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
continue;
err_drop_frame:
- dev->stats.rx_errors++;
- mvpp2_rx_error(port, rx_desc);
/* Return the buffer to the pool */
if (rx_status & MVPP2_RXD_BUF_HDR)
mvpp2_buff_hdr_pool_put(port, rx_desc, pool, rx_status);
else
mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
+err_drop_frame_retired:
+ dev->stats.rx_errors++;
+ mvpp2_rx_error(port, rx_desc);
}
if (xdp_ret & MVPP2_XDP_REDIR)
--
2.43.0
More information about the kernel-team
mailing list