On Mon, Jul 7, 2025 at 11:48 AM Jason Wang <jasowang@xxxxxxxxxx> wrote: > > On Sun, Jul 6, 2025 at 10:12 PM Bui Quang Minh <minhquangbui99@xxxxxxxxx> 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> > > --- > > drivers/net/virtio_net.c | 10 +++++++--- > > 1 file changed, 7 insertions(+), 3 deletions(-) > > > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > > index 5d674eb9a0f2..ead1cd2fb8af 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,16 @@ 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); > > + give_pages(rq, page); > > Should this be an independent fix? Btw, the page_to_skb() is really kind of messed up right now that it is used by both big and mergeable. We may need to consider splitting the logic in the future. Thanks > > > 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 > > > > Thanks