Patch "virtio-net: fix overflow inside virtnet_rq_alloc" has been added to the 6.12-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    virtio-net: fix overflow inside virtnet_rq_alloc

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     virtio-net-fix-overflow-inside-virtnet_rq_alloc.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 3f66e24cdbee6d4c94b867413ac067ccc6252064
Author: Xuan Zhuo <xuanzhuo@xxxxxxxxxxxxxxxxx>
Date:   Tue Oct 29 16:46:12 2024 +0800

    virtio-net: fix overflow inside virtnet_rq_alloc
    
    [ Upstream commit 6aacd1484468361d1d04badfe75f264fa5314864 ]
    
    When the frag just got a page, then may lead to regression on VM.
    Specially if the sysctl net.core.high_order_alloc_disable value is 1,
    then the frag always get a page when do refill.
    
    Which could see reliable crashes or scp failure (scp a file 100M in size
    to VM).
    
    The issue is that the virtnet_rq_dma takes up 16 bytes at the beginning
    of a new frag. When the frag size is larger than PAGE_SIZE,
    everything is fine. However, if the frag is only one page and the
    total size of the buffer and virtnet_rq_dma is larger than one page, an
    overflow may occur.
    
    The commit f9dac92ba908 ("virtio_ring: enable premapped mode whatever
    use_dma_api") introduced this problem. And we reverted some commits to
    fix this in last linux version. Now we try to enable it and fix this
    bug directly.
    
    Here, when the frag size is not enough, we reduce the buffer len to fix
    this problem.
    
    Reported-by: "Si-Wei Liu" <si-wei.liu@xxxxxxxxxx>
    Tested-by: Darren Kenny <darren.kenny@xxxxxxxxxx>
    Signed-off-by: Xuan Zhuo <xuanzhuo@xxxxxxxxxxxxxxxxx>
    Acked-by: Jason Wang <jasowang@xxxxxxxxxx>
    Signed-off-by: Paolo Abeni <pabeni@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 53a038fcbe991..c897afef0b414 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -946,9 +946,6 @@ static void *virtnet_rq_alloc(struct receive_queue *rq, u32 size, gfp_t gfp)
 	void *buf, *head;
 	dma_addr_t addr;
 
-	if (unlikely(!skb_page_frag_refill(size, alloc_frag, gfp)))
-		return NULL;
-
 	head = page_address(alloc_frag->page);
 
 	if (rq->do_dma) {
@@ -2443,6 +2440,9 @@ static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq,
 	len = SKB_DATA_ALIGN(len) +
 	      SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
 
+	if (unlikely(!skb_page_frag_refill(len, &rq->alloc_frag, gfp)))
+		return -ENOMEM;
+
 	buf = virtnet_rq_alloc(rq, len, gfp);
 	if (unlikely(!buf))
 		return -ENOMEM;
@@ -2545,6 +2545,12 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi,
 	 */
 	len = get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len, room);
 
+	if (unlikely(!skb_page_frag_refill(len + room, alloc_frag, gfp)))
+		return -ENOMEM;
+
+	if (!alloc_frag->offset && len + room + sizeof(struct virtnet_rq_dma) > alloc_frag->size)
+		len -= sizeof(struct virtnet_rq_dma);
+
 	buf = virtnet_rq_alloc(rq, len + room, gfp);
 	if (unlikely(!buf))
 		return -ENOMEM;




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux