> From: Bui Quang Minh <minhquangbu...@gmail.com> > Sent: 08 July 2025 08:12 PM > > Since commit 4959aebba8c0 ("virtio-net: use mtu size as buffer length for big > packets"), the allocated size for big packets is not MAX_SKB_FRAGS * > PAGE_SIZE anymore but depends on negotiated MTU. The number of > allocated frags for big packets is stored in > vi->big_packets_num_skbfrags. This commit fixes the received length > check corresponding to that change. The current incorrect check can lead to > NULL page pointer dereference in the below while loop when erroneous > length is received. Do you mean a device has copied X bytes in receive buffer but device reports X+Y bytes in the ring?
> > Fixes: 4959aebba8c0 ("virtio-net: use mtu size as buffer length for big > packets") > Signed-off-by: Bui Quang Minh <minhquangbu...@gmail.com> > --- > Changes in v2: > - Remove incorrect give_pages call > --- > drivers/net/virtio_net.c | 9 ++++++--- > 1 file changed, 6 insertions(+), 3 deletions(-) > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index > 5d674eb9a0f2..3a7f435c95ae 100644 > --- a/drivers/net/virtio_net.c > +++ b/drivers/net/virtio_net.c > @@ -823,7 +823,7 @@ static struct sk_buff *page_to_skb(struct virtnet_info > *vi, { > struct sk_buff *skb; > struct virtio_net_common_hdr *hdr; > - unsigned int copy, hdr_len, hdr_padded_len; > + unsigned int copy, hdr_len, hdr_padded_len, max_remaining_len; > struct page *page_to_free = NULL; > int tailroom, shinfo_size; > char *p, *hdr_p, *buf; > @@ -887,12 +887,15 @@ static struct sk_buff *page_to_skb(struct > virtnet_info *vi, > * tries to receive more than is possible. This is usually > * the case of a broken device. > */ > - if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) { > + BUG_ON(offset >= PAGE_SIZE); > + max_remaining_len = (unsigned int)PAGE_SIZE - offset; > + max_remaining_len += vi->big_packets_num_skbfrags * PAGE_SIZE; > + if (unlikely(len > max_remaining_len)) { > net_dbg_ratelimited("%s: too much data\n", skb->dev- > >name); > dev_kfree_skb(skb); > return NULL; > } > - BUG_ON(offset >= PAGE_SIZE); > + > while (len) { > unsigned int frag_size = min((unsigned)PAGE_SIZE - offset, > len); > skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, > -- > 2.43.0