Re: [PATCH net v3 2/2] octeon_ep_vf: fix skb frags overflow in the RX path

From: Maciej Fijalkowski

Date: Mon Jul 06 2026 - 06:42:44 EST


On Sat, Jul 04, 2026 at 02:15:11PM +0800, Maoyi Xie wrote:
> __octep_vf_oq_process_rx() has the same unbounded fragment loop as the PF
> driver. buff_info->len comes from the device response header, and one
> fragment is added per buffer_size chunk with no check against
> MAX_SKB_FRAGS. A long packet yields about 18 fragments, one past the
> default MAX_SKB_FRAGS of 17, so skb_add_rx_frag() writes past
> shinfo->frags[].
>
> The fragment count is now checked before napi_build_skb(). A packet that
> needs more fragments than the skb can hold is dropped.
> octep_vf_oq_drop_rx() drains its descriptors. The napi_build_skb()
> failure path now uses the same helper.
>
> Fixes: 1cd3b407977c ("octeon_ep_vf: add Tx/Rx processing and interrupt support")
> Co-developed-by: Kaixuan Li <kaixuan.li@xxxxxxxxxx>
> Signed-off-by: Kaixuan Li <kaixuan.li@xxxxxxxxxx>
> Signed-off-by: Maoyi Xie <maoyixie.tju@xxxxxxxxx>

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

> ---
> .../marvell/octeon_ep_vf/octep_vf_rx.c | 46 ++++++++++++-------
> 1 file changed, 30 insertions(+), 16 deletions(-)
>
> 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..aa77b673ae 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
> @@ -357,6 +357,29 @@ static inline u32 octep_vf_oq_next_idx(struct octep_vf_oq *oq, u32 idx)
> return (idx + 1 == oq->max_count) ? 0 : idx + 1;
> }
>
> +static void octep_vf_oq_drop_rx(struct octep_vf_oq *oq,
> + struct octep_vf_rx_buffer *buff_info,
> + u32 *read_idx, u32 *desc_used)
> +{
> + u16 data_len = buff_info->len - oq->max_single_buffer_size;
> +
> + (*desc_used)++;
> + *read_idx = octep_vf_oq_next_idx(oq, *read_idx);
> + while (data_len) {
> + dma_unmap_page(oq->dev, oq->desc_ring[*read_idx].buffer_ptr,
> + PAGE_SIZE, DMA_FROM_DEVICE);
> + buff_info = (struct octep_vf_rx_buffer *)
> + &oq->buff_info[*read_idx];
> + buff_info->page = NULL;
> + if (data_len < oq->buffer_size)
> + data_len = 0;
> + else
> + data_len -= oq->buffer_size;
> + (*desc_used)++;
> + *read_idx = octep_vf_oq_next_idx(oq, *read_idx);
> + }
> +}
> +
> /**
> * __octep_vf_oq_process_rx() - Process hardware Rx queue and push to stack.
> *
> @@ -431,25 +454,16 @@ static int __octep_vf_oq_process_rx(struct octep_vf_device *oct,
> struct skb_shared_info *shinfo;
> u16 data_len;
>
> + data_len = buff_info->len - oq->max_single_buffer_size;
> + if (DIV_ROUND_UP(data_len, oq->buffer_size) > MAX_SKB_FRAGS) {
> + octep_vf_oq_drop_rx(oq, buff_info, &read_idx, &desc_used);
> + continue;
> + }
> +
> skb = napi_build_skb((void *)resp_hw, PAGE_SIZE);
> if (!skb) {
> oq->stats->alloc_failures++;
> - desc_used++;
> - read_idx = octep_vf_oq_next_idx(oq, read_idx);
> - data_len = buff_info->len - oq->max_single_buffer_size;
> - while (data_len) {
> - dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
> - PAGE_SIZE, DMA_FROM_DEVICE);
> - buff_info = (struct octep_vf_rx_buffer *)
> - &oq->buff_info[read_idx];
> - buff_info->page = NULL;
> - if (data_len < oq->buffer_size)
> - data_len = 0;
> - else
> - data_len -= oq->buffer_size;
> - desc_used++;
> - read_idx = octep_vf_oq_next_idx(oq, read_idx);
> - }
> + octep_vf_oq_drop_rx(oq, buff_info, &read_idx, &desc_used);
> continue;
> }
> rx_bytes += buff_info->len;
> --
> 2.34.1
>