Re: [PATCH net v4 2/3] octeon_ep_vf: Fix RX page leak on napi_build_skb() failure

From: Maciej Fijalkowski

Date: Mon Jul 06 2026 - 12:40:42 EST


On Mon, Jul 06, 2026 at 11:02:07PM +0800, Maoyi Xie wrote:
> From: Guangshuo Li <lgs201920130244@xxxxxxxxx>
>
> __octep_vf_oq_process_rx() clears buff_info->page before building an skb
> from the RX page. On the success path the page is consumed by the skb,
> either as the skb head or as an RX fragment.
>
> If napi_build_skb() fails, however, the page is not consumed by an skb.
> The error path advances the descriptor and leaves the ring slot cleared,
> so the page is no longer tracked and is leaked. In the multi-fragment
> case, the remaining fragment pages are also unmapped and removed from
> their ring slots without being released.
>
> Release the head page when napi_build_skb() fails, and release each
> remaining fragment page before clearing its ring slot.
>
> Fixes: dd66b4285470 ("octeon_ep_vf: add NULL check for napi_build_skb()")
> Signed-off-by: Guangshuo Li <lgs201920130244@xxxxxxxxx>

Reviewed-by: Maciej Fijalkowski <maciej.fijalkowski@xxxxxxxxx>

> ---
> drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
> index d982474082..302559b16b 100644
> --- a/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
> +++ b/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_rx.c
> @@ -418,6 +418,7 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
> skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
> if (!skb) {
> oq->stats->alloc_failures++;
> + put_page(virt_to_page(resp_hw));
> desc_used++;
> read_idx = octep_vf_oq_next_idx(oq, read_idx);
> continue;
> @@ -434,6 +435,7 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
> skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
> if (!skb) {
> oq->stats->alloc_failures++;
> + put_page(virt_to_page(resp_hw));
> desc_used++;
> read_idx = octep_vf_oq_next_idx(oq, read_idx);
> data_len = buff_info->len - oq->max_single_buffer_size;
> @@ -442,6 +444,7 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
> PAGE_SIZE, DMA_FROM_DEVICE);
> buff_info = (struct octep_vf_rx_buffer *)
> &oq->buff_info[read_idx];
> + put_page(buff_info->page);
> buff_info->page = NULL;
> if (data_len < oq->buffer_size)
> data_len = 0;
> --
> 2.34.1
>