From d0930489f860de14ca8013bda275e7756cf5af59 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Wed, 28 Feb 2024 20:33:12 +0900 Subject: [PATCH 1/8] hw/nvme: Use pcie_sriov_num_vfs() (bsc#1220065, CVE-2024-26328) nvme_sriov_pre_write_ctrl() used to directly inspect SR-IOV configurations to know the number of VFs being disabled due to SR-IOV configuration writes, but the logic was flawed and resulted in out-of-bound memory access. It assumed PCI_SRIOV_NUM_VF always has the number of currently enabled VFs, but it actually doesn't in the following cases: - PCI_SRIOV_NUM_VF has been set but PCI_SRIOV_CTRL_VFE has never been. - PCI_SRIOV_NUM_VF was written after PCI_SRIOV_CTRL_VFE was set. - VFs were only partially enabled because of realization failure. It is a responsibility of pcie_sriov to interpret SR-IOV configurations and pcie_sriov does it correctly, so use pcie_sriov_num_vfs(), which it provides, to get the number of enabled VFs before and after SR-IOV configuration writes. Cc: qemu-stable@nongnu.org Fixes: CVE-2024-26328 Fixes: 11871f53ef8e ("hw/nvme: Add support for the Virtualization Management command") Suggested-by: Michael S. Tsirkin Signed-off-by: Akihiko Odaki Message-Id: <20240228-reuse-v8-1-282660281e60@daynix.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit 91bb64a8d2014fda33a81fcf0fce37340f0d3b0c) References: bsc#1220065 Signed-off-by: Dario Faggioli --- hw/nvme/ctrl.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 76fe039704..2860a9bed1 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -8466,36 +8466,26 @@ static void nvme_pci_reset(DeviceState *qdev) nvme_ctrl_reset(n, NVME_RESET_FUNCTION); } -static void nvme_sriov_pre_write_ctrl(PCIDevice *dev, uint32_t address, - uint32_t val, int len) +static void nvme_sriov_post_write_config(PCIDevice *dev, uint16_t old_num_vfs) { NvmeCtrl *n = NVME(dev); NvmeSecCtrlEntry *sctrl; - uint16_t sriov_cap = dev->exp.sriov_cap; - uint32_t off = address - sriov_cap; - int i, num_vfs; + int i; - if (!sriov_cap) { - return; - } - - if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) { - if (!(val & PCI_SRIOV_CTRL_VFE)) { - num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); - for (i = 0; i < num_vfs; i++) { - sctrl = &n->sec_ctrl_list.sec[i]; - nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false); - } - } + for (i = pcie_sriov_num_vfs(dev); i < old_num_vfs; i++) { + sctrl = &n->sec_ctrl_list.sec[i]; + nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false); } } static void nvme_pci_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int len) { - nvme_sriov_pre_write_ctrl(dev, address, val, len); + uint16_t old_num_vfs = pcie_sriov_num_vfs(dev); + pci_default_write_config(dev, address, val, len); pcie_cap_flr_write_config(dev, address, val, len); + nvme_sriov_post_write_config(dev, old_num_vfs); } static const VMStateDescription nvme_vmstate = { -- 2.51.1 From 158c1626b70348e8f23ea4390867113bc24a036c Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Wed, 28 Feb 2024 20:33:12 +0900 Subject: [PATCH 2/8] hw/nvme: Use pcie_sriov_num_vfs() (bsc#1220065, CVE-2024-26328) nvme_sriov_pre_write_ctrl() used to directly inspect SR-IOV configurations to know the number of VFs being disabled due to SR-IOV configuration writes, but the logic was flawed and resulted in out-of-bound memory access. It assumed PCI_SRIOV_NUM_VF always has the number of currently enabled VFs, but it actually doesn't in the following cases: - PCI_SRIOV_NUM_VF has been set but PCI_SRIOV_CTRL_VFE has never been. - PCI_SRIOV_NUM_VF was written after PCI_SRIOV_CTRL_VFE was set. - VFs were only partially enabled because of realization failure. It is a responsibility of pcie_sriov to interpret SR-IOV configurations and pcie_sriov does it correctly, so use pcie_sriov_num_vfs(), which it provides, to get the number of enabled VFs before and after SR-IOV configuration writes. Cc: qemu-stable@nongnu.org Fixes: CVE-2024-26328 Fixes: 11871f53ef8e ("hw/nvme: Add support for the Virtualization Management command") Suggested-by: Michael S. Tsirkin Signed-off-by: Akihiko Odaki Message-Id: <20240228-reuse-v8-1-282660281e60@daynix.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin (cherry picked from commit 91bb64a8d2014fda33a81fcf0fce37340f0d3b0c) References: bsc#1220065 Signed-off-by: Dario Faggioli --- hw/nvme/ctrl.c | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 76fe039704..2860a9bed1 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -8466,36 +8466,26 @@ static void nvme_pci_reset(DeviceState *qdev) nvme_ctrl_reset(n, NVME_RESET_FUNCTION); } -static void nvme_sriov_pre_write_ctrl(PCIDevice *dev, uint32_t address, - uint32_t val, int len) +static void nvme_sriov_post_write_config(PCIDevice *dev, uint16_t old_num_vfs) { NvmeCtrl *n = NVME(dev); NvmeSecCtrlEntry *sctrl; - uint16_t sriov_cap = dev->exp.sriov_cap; - uint32_t off = address - sriov_cap; - int i, num_vfs; + int i; - if (!sriov_cap) { - return; - } - - if (range_covers_byte(off, len, PCI_SRIOV_CTRL)) { - if (!(val & PCI_SRIOV_CTRL_VFE)) { - num_vfs = pci_get_word(dev->config + sriov_cap + PCI_SRIOV_NUM_VF); - for (i = 0; i < num_vfs; i++) { - sctrl = &n->sec_ctrl_list.sec[i]; - nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false); - } - } + for (i = pcie_sriov_num_vfs(dev); i < old_num_vfs; i++) { + sctrl = &n->sec_ctrl_list.sec[i]; + nvme_virt_set_state(n, le16_to_cpu(sctrl->scid), false); } } static void nvme_pci_write_config(PCIDevice *dev, uint32_t address, uint32_t val, int len) { - nvme_sriov_pre_write_ctrl(dev, address, val, len); + uint16_t old_num_vfs = pcie_sriov_num_vfs(dev); + pci_default_write_config(dev, address, val, len); pcie_cap_flr_write_config(dev, address, val, len); + nvme_sriov_post_write_config(dev, old_num_vfs); } static const VMStateDescription nvme_vmstate = { -- 2.51.1 From 3a4f25dd9a1fed535a5cba30565d43fd9ceb39e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 9 Apr 2024 16:19:27 +0200 Subject: [PATCH 3/8] hw/sd/sdhci: Do not update TRNMOD when Command Inhibit (DAT) is set (bsc#1222845, CVE-2024-3447) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per "SD Host Controller Standard Specification Version 3.00": * 2.2.5 Transfer Mode Register (Offset 00Ch) Writes to this register shall be ignored when the Command Inhibit (DAT) in the Present State register is 1. Do not update the TRNMOD register when Command Inhibit (DAT) bit is set to avoid the present-status register going out of sync, leading to malicious guest using DMA mode and overflowing the FIFO buffer: $ cat << EOF | qemu-system-i386 \ -display none -nographic -nodefaults \ -machine accel=qtest -m 512M \ -device sdhci-pci,sd-spec-version=3 \ -device sd-card,drive=mydrive \ -drive if=none,index=0,file=null-co://,format=raw,id=mydrive \ -qtest stdio outl 0xcf8 0x80001013 outl 0xcfc 0x91 outl 0xcf8 0x80001001 outl 0xcfc 0x06000000 write 0x9100002c 0x1 0x05 write 0x91000058 0x1 0x16 write 0x91000005 0x1 0x04 write 0x91000028 0x1 0x08 write 0x16 0x1 0x21 write 0x19 0x1 0x20 write 0x9100000c 0x1 0x01 write 0x9100000e 0x1 0x20 write 0x9100000f 0x1 0x00 write 0x9100000c 0x1 0x00 write 0x91000020 0x1 0x00 EOF Stack trace (part): ================================================================= ==89993==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x615000029900 at pc 0x55d5f885700d bp 0x7ffc1e1e9470 sp 0x7ffc1e1e9468 WRITE of size 1 at 0x615000029900 thread T0 #0 0x55d5f885700c in sdhci_write_dataport hw/sd/sdhci.c:564:39 #1 0x55d5f8849150 in sdhci_write hw/sd/sdhci.c:1223:13 #2 0x55d5fa01db63 in memory_region_write_accessor system/memory.c:497:5 #3 0x55d5fa01d245 in access_with_adjusted_size system/memory.c:573:18 #4 0x55d5fa01b1a9 in memory_region_dispatch_write system/memory.c:1521:16 #5 0x55d5fa09f5c9 in flatview_write_continue system/physmem.c:2711:23 #6 0x55d5fa08f78b in flatview_write system/physmem.c:2753:12 #7 0x55d5fa08f258 in address_space_write system/physmem.c:2860:18 ... 0x615000029900 is located 0 bytes to the right of 512-byte region [0x615000029700,0x615000029900) allocated by thread T0 here: #0 0x55d5f7237b27 in __interceptor_calloc #1 0x7f9e36dd4c50 in g_malloc0 #2 0x55d5f88672f7 in sdhci_pci_realize hw/sd/sdhci-pci.c:36:5 #3 0x55d5f844b582 in pci_qdev_realize hw/pci/pci.c:2092:9 #4 0x55d5fa2ee74b in device_set_realized hw/core/qdev.c:510:13 #5 0x55d5fa325bfb in property_set_bool qom/object.c:2358:5 #6 0x55d5fa31ea45 in object_property_set qom/object.c:1472:5 #7 0x55d5fa332509 in object_property_set_qobject om/qom-qobject.c:28:10 #8 0x55d5fa31f6ed in object_property_set_bool qom/object.c:1541:15 #9 0x55d5fa2e2948 in qdev_realize hw/core/qdev.c:292:12 #10 0x55d5f8eed3f1 in qdev_device_add_from_qdict system/qdev-monitor.c:719:10 #11 0x55d5f8eef7ff in qdev_device_add system/qdev-monitor.c:738:11 #12 0x55d5f8f211f0 in device_init_func system/vl.c:1200:11 #13 0x55d5fad0877d in qemu_opts_foreach util/qemu-option.c:1135:14 #14 0x55d5f8f0df9c in qemu_create_cli_devices system/vl.c:2638:5 #15 0x55d5f8f0db24 in qmp_x_exit_preconfig system/vl.c:2706:5 #16 0x55d5f8f14dc0 in qemu_init system/vl.c:3737:9 ... SUMMARY: AddressSanitizer: heap-buffer-overflow hw/sd/sdhci.c:564:39 in sdhci_write_dataport Add assertions to ensure the fifo_buffer[] is not overflowed by malicious accesses to the Buffer Data Port register. Fixes: CVE-2024-3447 Cc: qemu-stable@nongnu.org Fixes: d7dfca0807 ("hw/sdhci: introduce standard SD host controller") Buglink: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=58813 Reported-by: Alexander Bulekov Reported-by: Chuhong Yuan Signed-off-by: Peter Maydell Message-Id: Signed-off-by: Philippe Mathieu-Daudé Message-Id: <20240409145524.27913-1-philmd@linaro.org> (cherry picked from commit 9e4b27ca6bf4974f169bbca7f3dca117b1208b6f) References: bsc#1222845 Signed-off-by: Dario Faggioli --- hw/sd/sdhci.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 40473b0db0..e95ea34895 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -473,6 +473,7 @@ static uint32_t sdhci_read_dataport(SDHCIState *s, unsigned size) } for (i = 0; i < size; i++) { + assert(s->data_count < s->buf_maxsz); value |= s->fifo_buffer[s->data_count] << i * 8; s->data_count++; /* check if we've read all valid data (blksize bytes) from buffer */ @@ -561,6 +562,7 @@ static void sdhci_write_dataport(SDHCIState *s, uint32_t value, unsigned size) } for (i = 0; i < size; i++) { + assert(s->data_count < s->buf_maxsz); s->fifo_buffer[s->data_count] = value & 0xFF; s->data_count++; value >>= 8; @@ -1208,6 +1210,12 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size) if (!(s->capareg & R_SDHC_CAPAB_SDMA_MASK)) { value &= ~SDHC_TRNS_DMA; } + + /* TRNMOD writes are inhibited while Command Inhibit (DAT) is true */ + if (s->prnsts & SDHC_DATA_INHIBIT) { + mask |= 0xffff; + } + MASKED_WRITE(s->trnmod, mask, value & SDHC_TRNMOD_MASK); MASKED_WRITE(s->cmdreg, mask >> 16, value >> 16); -- 2.51.1 From 17313718873df10f26fc6ec213b5ea080d0ebb9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 4 Apr 2024 20:56:11 +0200 Subject: [PATCH 4/8] hw/virtio: Introduce virtio_bh_new_guarded() helper (bsc#1222843, CVE-2024-3446) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce virtio_bh_new_guarded(), similar to qemu_bh_new_guarded() but using the transport memory guard, instead of the device one (there can only be one virtio device per virtio bus). Inspired-by: Gerd Hoffmann Reviewed-by: Gerd Hoffmann Acked-by: Michael S. Tsirkin Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Message-Id: <20240409105537.18308-2-philmd@linaro.org> (cherry picked from commit ec0504b989ca61e03636384d3602b7bf07ffe4da) References: bsc#1222843 Signed-off-by: Dario Faggioli --- hw/virtio/virtio.c | 10 ++++++++++ include/hw/virtio/virtio.h | 7 +++++++ 2 files changed, 17 insertions(+) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 356d690cc9..86ab502959 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -4137,3 +4137,13 @@ static void virtio_register_types(void) } type_init(virtio_register_types) + +QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev, + QEMUBHFunc *cb, void *opaque, + const char *name) +{ + DeviceState *transport = qdev_get_parent_bus(dev)->parent; + + return qemu_bh_new_full(cb, opaque, name, + &transport->mem_reentrancy_guard); +} diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index c8f72850bc..7d5ffdc145 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -22,6 +22,7 @@ #include "standard-headers/linux/virtio_config.h" #include "standard-headers/linux/virtio_ring.h" #include "qom/object.h" +#include "block/aio.h" /* * A guest should never accept this. It implies negotiation is broken @@ -508,4 +509,10 @@ static inline bool virtio_device_disabled(VirtIODevice *vdev) bool virtio_legacy_allowed(VirtIODevice *vdev); bool virtio_legacy_check_disabled(VirtIODevice *vdev); +QEMUBH *virtio_bh_new_guarded_full(DeviceState *dev, + QEMUBHFunc *cb, void *opaque, + const char *name); +#define virtio_bh_new_guarded(dev, cb, opaque) \ + virtio_bh_new_guarded_full((dev), (cb), (opaque), (stringify(cb))) + #endif -- 2.51.1 From 955f514223d9946e82967830803cc91a89694216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 4 Apr 2024 20:56:27 +0200 Subject: [PATCH 5/8] hw/display/virtio-gpu: Protect from DMA re-entrancy bugs (bsc#1222843, CVE-2024-3446) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() so the bus and device use the same guard. Otherwise the DMA-reentrancy protection can be bypassed: $ cat << EOF | qemu-system-i386 -display none -nodefaults \ -machine q35,accel=qtest \ -m 512M \ -device virtio-gpu \ -qtest stdio outl 0xcf8 0x80000820 outl 0xcfc 0xe0004000 outl 0xcf8 0x80000804 outw 0xcfc 0x06 write 0xe0004030 0x4 0x024000e0 write 0xe0004028 0x1 0xff write 0xe0004020 0x4 0x00009300 write 0xe000401c 0x1 0x01 write 0x101 0x1 0x04 write 0x103 0x1 0x1c write 0x9301c8 0x1 0x18 write 0x105 0x1 0x1c write 0x107 0x1 0x1c write 0x109 0x1 0x1c write 0x10b 0x1 0x00 write 0x10d 0x1 0x00 write 0x10f 0x1 0x00 write 0x111 0x1 0x00 write 0x113 0x1 0x00 write 0x115 0x1 0x00 write 0x117 0x1 0x00 write 0x119 0x1 0x00 write 0x11b 0x1 0x00 write 0x11d 0x1 0x00 write 0x11f 0x1 0x00 write 0x121 0x1 0x00 write 0x123 0x1 0x00 write 0x125 0x1 0x00 write 0x127 0x1 0x00 write 0x129 0x1 0x00 write 0x12b 0x1 0x00 write 0x12d 0x1 0x00 write 0x12f 0x1 0x00 write 0x131 0x1 0x00 write 0x133 0x1 0x00 write 0x135 0x1 0x00 write 0x137 0x1 0x00 write 0x139 0x1 0x00 write 0xe0007003 0x1 0x00 EOF ... ================================================================= ==276099==ERROR: AddressSanitizer: heap-use-after-free on address 0x60d000011178 at pc 0x562cc3b736c7 bp 0x7ffed49dee60 sp 0x7ffed49dee58 READ of size 8 at 0x60d000011178 thread T0 #0 0x562cc3b736c6 in virtio_gpu_ctrl_response hw/display/virtio-gpu.c:180:42 #1 0x562cc3b7c40b in virtio_gpu_ctrl_response_nodata hw/display/virtio-gpu.c:192:5 #2 0x562cc3b7c40b in virtio_gpu_simple_process_cmd hw/display/virtio-gpu.c:1015:13 #3 0x562cc3b82873 in virtio_gpu_process_cmdq hw/display/virtio-gpu.c:1050:9 #4 0x562cc4a85514 in aio_bh_call util/async.c:169:5 #5 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13 #6 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5 #7 0x562cc4a8a2da in aio_ctx_dispatch util/async.c:358:5 #8 0x7f36840547a8 in g_main_context_dispatch (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x547a8) #9 0x562cc4a8b753 in glib_pollfds_poll util/main-loop.c:290:9 #10 0x562cc4a8b753 in os_host_main_loop_wait util/main-loop.c:313:5 #11 0x562cc4a8b753 in main_loop_wait util/main-loop.c:592:11 #12 0x562cc3938186 in qemu_main_loop system/runstate.c:782:9 #13 0x562cc43b7af5 in qemu_default_main system/main.c:37:14 #14 0x7f3683a6c189 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 #15 0x7f3683a6c244 in __libc_start_main csu/../csu/libc-start.c:381:3 #16 0x562cc2a58ac0 in _start (qemu-system-i386+0x231bac0) 0x60d000011178 is located 56 bytes inside of 136-byte region [0x60d000011140,0x60d0000111c8) freed by thread T0 here: #0 0x562cc2adb662 in __interceptor_free (qemu-system-i386+0x239e662) #1 0x562cc3b86b21 in virtio_gpu_reset hw/display/virtio-gpu.c:1524:9 #2 0x562cc416e20e in virtio_reset hw/virtio/virtio.c:2145:9 #3 0x562cc37c5644 in virtio_pci_reset hw/virtio/virtio-pci.c:2249:5 #4 0x562cc4233758 in memory_region_write_accessor system/memory.c:497:5 #5 0x562cc4232eea in access_with_adjusted_size system/memory.c:573:18 previously allocated by thread T0 here: #0 0x562cc2adb90e in malloc (qemu-system-i386+0x239e90e) #1 0x7f368405a678 in g_malloc (/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5a678) #2 0x562cc4163ffc in virtqueue_split_pop hw/virtio/virtio.c:1612:12 #3 0x562cc4163ffc in virtqueue_pop hw/virtio/virtio.c:1783:16 #4 0x562cc3b91a95 in virtio_gpu_handle_ctrl hw/display/virtio-gpu.c:1112:15 #5 0x562cc4a85514 in aio_bh_call util/async.c:169:5 #6 0x562cc4a85c52 in aio_bh_poll util/async.c:216:13 #7 0x562cc4a1a79b in aio_dispatch util/aio-posix.c:423:5 SUMMARY: AddressSanitizer: heap-use-after-free hw/display/virtio-gpu.c:180:42 in virtio_gpu_ctrl_response With this change, the same reproducer triggers: qemu-system-i386: warning: Blocked re-entrant IO on MemoryRegion: virtio-pci-common-virtio-gpu at addr: 0x6 Fixes: CVE-2024-3446 Cc: qemu-stable@nongnu.org Reported-by: Alexander Bulekov Reported-by: Yongkang Jia Reported-by: Xiao Lei Reported-by: Yiming Tao Buglink: https://bugs.launchpad.net/qemu/+bug/1888606 Reviewed-by: Gerd Hoffmann Acked-by: Michael S. Tsirkin Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Message-Id: <20240409105537.18308-3-philmd@linaro.org> (cherry picked from commit ba28e0ff4d95b56dc334aac2730ab3651ffc3132) References: bsc#1222843 Signed-off-by: Dario Faggioli --- hw/display/virtio-gpu.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index b016d3bac8..a7b16ba072 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1463,10 +1463,8 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) g->ctrl_vq = virtio_get_queue(vdev, 0); g->cursor_vq = virtio_get_queue(vdev, 1); - g->ctrl_bh = qemu_bh_new_guarded(virtio_gpu_ctrl_bh, g, - &qdev->mem_reentrancy_guard); - g->cursor_bh = qemu_bh_new_guarded(virtio_gpu_cursor_bh, g, - &qdev->mem_reentrancy_guard); + g->ctrl_bh = virtio_bh_new_guarded(qdev, virtio_gpu_ctrl_bh, g); + g->cursor_bh = virtio_bh_new_guarded(qdev, virtio_gpu_cursor_bh, g); g->reset_bh = qemu_bh_new(virtio_gpu_reset_bh, g); qemu_cond_init(&g->reset_cond); QTAILQ_INIT(&g->reslist); -- 2.51.1 From f549a7af8cc51977b3781a278afd7429c0987def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 4 Apr 2024 20:56:35 +0200 Subject: [PATCH 6/8] hw/char/virtio-serial-bus: Protect from DMA re-entrancy bugs (bsc#1222843, CVE-2024-3446) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() so the bus and device use the same guard. Otherwise the DMA-reentrancy protection can be bypassed. Fixes: CVE-2024-3446 Cc: qemu-stable@nongnu.org Suggested-by: Alexander Bulekov Reviewed-by: Gerd Hoffmann Acked-by: Michael S. Tsirkin Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Message-Id: <20240409105537.18308-4-philmd@linaro.org> (cherry picked from commit b4295bff25f7b50de1d9cc94a9c6effd40056bca) References: bsc#1222843 Signed-off-by: Dario Faggioli --- hw/char/virtio-serial-bus.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index dd619f0731..1221fb7f15 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -985,8 +985,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) return; } - port->bh = qemu_bh_new_guarded(flush_queued_data_bh, port, - &dev->mem_reentrancy_guard); + port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port); port->elem = NULL; } -- 2.51.1 From 9d1992de90be213feb6f50ebc47e1f936bcc9f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Thu, 4 Apr 2024 20:56:41 +0200 Subject: [PATCH 7/8] hw/virtio/virtio-crypto: Protect from DMA re-entrancy bugs (bsc#1222843, CVE-2024-3446) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace qemu_bh_new_guarded() by virtio_bh_new_guarded() so the bus and device use the same guard. Otherwise the DMA-reentrancy protection can be bypassed. Fixes: CVE-2024-3446 Cc: qemu-stable@nongnu.org Suggested-by: Alexander Bulekov Reviewed-by: Gerd Hoffmann Acked-by: Michael S. Tsirkin Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Michael S. Tsirkin Message-Id: <20240409105537.18308-5-philmd@linaro.org> (cherry picked from commit f4729ec39ad97a42ceaa7b5697f84f440ea6e5dc) References: bsc#1222843 Signed-off-by: Dario Faggioli --- hw/virtio/virtio-crypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index 0e2cc8d5a8..4aaced74be 100644 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -1080,8 +1080,8 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp) vcrypto->vqs[i].dataq = virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh); vcrypto->vqs[i].dataq_bh = - qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i], - &dev->mem_reentrancy_guard); + virtio_bh_new_guarded(dev, virtio_crypto_dataq_bh, + &vcrypto->vqs[i]); vcrypto->vqs[i].vcrypto = vcrypto; } -- 2.51.1 From 651ccca79d20882665f7b278a1d40ee38a77f106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Tue, 9 Apr 2024 19:54:05 +0200 Subject: [PATCH 8/8] hw/net/net_tx_pkt: Fix overrun in update_sctp_checksum() (bsc#1222841, CVE-2024-3567) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a fragmented packet size is too short, do not try to calculate its checksum. Reproduced using: $ cat << EOF | qemu-system-i386 -display none -nodefaults \ -machine q35,accel=qtest -m 32M \ -device igb,netdev=net0 \ -netdev user,id=net0 \ -qtest stdio outl 0xcf8 0x80000810 outl 0xcfc 0xe0000000 outl 0xcf8 0x80000804 outw 0xcfc 0x06 write 0xe0000403 0x1 0x02 writel 0xe0003808 0xffffffff write 0xe000381a 0x1 0x5b write 0xe000381b 0x1 0x00 EOF Assertion failed: (offset == 0), function iov_from_buf_full, file util/iov.c, line 39. #1 0x5575e81e952a in iov_from_buf_full qemu/util/iov.c:39:5 #2 0x5575e6500768 in net_tx_pkt_update_sctp_checksum qemu/hw/net/net_tx_pkt.c:144:9 #3 0x5575e659f3e1 in igb_setup_tx_offloads qemu/hw/net/igb_core.c:478:11 #4 0x5575e659f3e1 in igb_tx_pkt_send qemu/hw/net/igb_core.c:552:10 #5 0x5575e659f3e1 in igb_process_tx_desc qemu/hw/net/igb_core.c:671:17 #6 0x5575e659f3e1 in igb_start_xmit qemu/hw/net/igb_core.c:903:9 #7 0x5575e659f3e1 in igb_set_tdt qemu/hw/net/igb_core.c:2812:5 #8 0x5575e657d6a4 in igb_core_write qemu/hw/net/igb_core.c:4248:9 Fixes: CVE-2024-3567 Cc: qemu-stable@nongnu.org Reported-by: Zheyu Ma Fixes: f199b13bc1 ("igb: Implement Tx SCTP CSO") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2273 Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: Akihiko Odaki Acked-by: Jason Wang Message-Id: <20240410070459.49112-1-philmd@linaro.org> (cherry picked from commit 83ddb3dbba2ee0f1767442ae6ee665058aeb1093) References: bsc#1222841 Signed-off-by: Dario Faggioli --- hw/net/net_tx_pkt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/net/net_tx_pkt.c b/hw/net/net_tx_pkt.c index 2e5f58b3c9..d40d508a11 100644 --- a/hw/net/net_tx_pkt.c +++ b/hw/net/net_tx_pkt.c @@ -141,6 +141,10 @@ bool net_tx_pkt_update_sctp_checksum(struct NetTxPkt *pkt) uint32_t csum = 0; struct iovec *pl_start_frag = pkt->vec + NET_TX_PKT_PL_START_FRAG; + if (iov_size(pl_start_frag, pkt->payload_frags) < 8 + sizeof(csum)) { + return false; + } + if (iov_from_buf(pl_start_frag, pkt->payload_frags, 8, &csum, sizeof(csum)) < sizeof(csum)) { return false; } -- 2.51.1