From: Xiang Mei Date: Tue, 16 Jun 2026 04:28:37 +0000 (-0700) Subject: virtio-net: fix len check in receive_big() X-Git-Tag: v7.2-rc1~29^2~102 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9e5ad06ea826322ce8c58b4a68442a96f600c3c4;p=thirdparty%2Flinux.git virtio-net: fix len check in receive_big() receive_big() bounds the device-announced length by (big_packets_num_skbfrags + 1) * PAGE_SIZE. That is still too loose: add_recvbuf_big() sets sg[1] to start at offset sizeof(struct padded_vnet_hdr) into the first page, so the chain actually carries hdr_len + (PAGE_SIZE - sizeof(padded_vnet_hdr)) + big_packets_num_skbfrags * PAGE_SIZE bytes -- 20 bytes less than the check allows for the common hdr_len == 12 case. A malicious virtio backend can announce a len in that gap. page_to_skb() then walks one frag past the page chain, storing a NULL page->private into skb_shinfo()->frags[MAX_SKB_FRAGS], which is both an out-of-bounds write past the static frag array and a NULL frag handed up the rx path. Bound len by the size add_recvbuf_big() actually advertised. Fixes: 0c716703965f ("virtio-net: fix received length check in big packets") Reported-by: Weiming Shi Signed-off-by: Xiang Mei Reviewed-by: Xuan Zhuo Acked-by: Michael S. Tsirkin Reviewed-by: Bui Quang Minh Link: https://patch.msgid.link/20260616042837.2249468-1-xmei5@asu.edu Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7d2eeb9b12266..26afa6341d161 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -1999,15 +1999,18 @@ static struct sk_buff *receive_big(struct net_device *dev, struct virtnet_rq_stats *stats) { struct page *page = buf; + unsigned long max_len; struct sk_buff *skb; + max_len = (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE - + sizeof(struct padded_vnet_hdr) + vi->hdr_len; + /* Make sure that len does not exceed the size allocated in * add_recvbuf_big. */ - if (unlikely(len > (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE)) { + if (unlikely(len > max_len)) { pr_debug("%s: rx error: len %u exceeds allocated size %lu\n", - dev->name, len, - (vi->big_packets_num_skbfrags + 1) * PAGE_SIZE); + dev->name, len, max_len); goto err; }