On Tue, Jul 08, 2025 at 09:42:06PM +0700, Bui Quang Minh wrote: > 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. > > Fixes: 4959aebba8c0 ("virtio-net: use mtu size as buffer length for big packets") > Signed-off-by: Bui Quang Minh <minhquangbui99@xxxxxxxxx> Acked-by: Michael S. Tsirkin <mst@xxxxxxxxxx> > --- > 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