qemu/virtio-net-correctly-copy-vnet-header-when-flushing-.patch
Jiabo Feng f7e6c9d33c QEMU update to version 6.2.0-89
- qga-win: Fix guest-get-fsinfo multi-disks collection
- hw/timer: fix systick trace message
- virtio-net: correctly copy vnet header when flushing TX (CVE-2023-6693)
- ui/clipboard: mark type as not available when there is no data (CVE-2023-6683)
- esp: restrict non-DMA transfer length to that of available data (CVE-2024-24474)
- hw/scsi/lsi53c895a: add missing decrement of reentrancy counter
- hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI controller (CVE-2023-0330)
- net: Update MemReentrancyGuard for NIC (CVE-2023-3019)
- net: Provide MemReentrancyGuard * to qemu_new_nic()

Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com>
(cherry picked from commit 18db08e0e64d982b88ad7f29ccd49b19e8c656f0)
2024-03-09 16:58:34 +08:00

73 lines
2.9 KiB
Diff

From 15f89b0447956d16f9ff20e243fa9076e5dd9af1 Mon Sep 17 00:00:00 2001
From: Jason Wang <jasowang@redhat.com>
Date: Tue, 2 Jan 2024 11:29:01 +0800
Subject: [PATCH] virtio-net: correctly copy vnet header when flushing TX
(CVE-2023-6693)
When HASH_REPORT is negotiated, the guest_hdr_len might be larger than
the size of the mergeable rx buffer header. Using
virtio_net_hdr_mrg_rxbuf during the header swap might lead a stack
overflow in this case. Fixing this by using virtio_net_hdr_v1_hash
instead.
Reported-by: Xiao Lei <leixiao.nop@zju.edu.cn>
Cc: Yuri Benditovich <yuri.benditovich@daynix.com>
Cc: qemu-stable@nongnu.org
Cc: Mauro Matteo Cascella <mcascell@redhat.com>
Fixes: CVE-2023-6693
Fixes: e22f0603fb2f ("virtio-net: reference implementation of hash report")
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
hw/net/virtio-net.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index d7405c3bf1..cdf1313053 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -600,6 +600,11 @@ static void virtio_net_set_mrg_rx_bufs(VirtIONet *n, int mergeable_rx_bufs,
n->mergeable_rx_bufs = mergeable_rx_bufs;
+ /*
+ * Note: when extending the vnet header, please make sure to
+ * change the vnet header copying logic in virtio_net_flush_tx()
+ * as well.
+ */
if (version_1) {
n->guest_hdr_len = hash_report ?
sizeof(struct virtio_net_hdr_v1_hash) :
@@ -2586,7 +2591,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
ssize_t ret;
unsigned int out_num;
struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1], *out_sg;
- struct virtio_net_hdr_mrg_rxbuf mhdr;
+ struct virtio_net_hdr_v1_hash vhdr;
elem = virtqueue_pop(q->tx_vq, sizeof(VirtQueueElement));
if (!elem) {
@@ -2603,7 +2608,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
}
if (n->has_vnet_hdr) {
- if (iov_to_buf(out_sg, out_num, 0, &mhdr, n->guest_hdr_len) <
+ if (iov_to_buf(out_sg, out_num, 0, &vhdr, n->guest_hdr_len) <
n->guest_hdr_len) {
virtio_error(vdev, "virtio-net header incorrect");
virtqueue_detach_element(q->tx_vq, elem, 0);
@@ -2611,8 +2616,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
return -EINVAL;
}
if (n->needs_vnet_hdr_swap) {
- virtio_net_hdr_swap(vdev, (void *) &mhdr);
- sg2[0].iov_base = &mhdr;
+ virtio_net_hdr_swap(vdev, (void *) &vhdr);
+ sg2[0].iov_base = &vhdr;
sg2[0].iov_len = n->guest_hdr_len;
out_num = iov_copy(&sg2[1], ARRAY_SIZE(sg2) - 1,
out_sg, out_num,
--
2.27.0