diff --git a/Fixed-the-early-version-of-CVE-2022-4144-patch-is-no.patch b/Fixed-the-early-version-of-CVE-2022-4144-patch-is-no.patch new file mode 100644 index 0000000000000000000000000000000000000000..9eee96170ef82938dd0c4ac4a3f2ff27a37d90c5 --- /dev/null +++ b/Fixed-the-early-version-of-CVE-2022-4144-patch-is-no.patch @@ -0,0 +1,38 @@ +From a99239d0d19353c7426f0d9288a1ca0826a76149 Mon Sep 17 00:00:00 2001 +From: liuhaipeng 00050065 +Date: Mon, 15 Jan 2024 10:44:26 +0800 +Subject: [PATCH] Fixed the early version of CVE-2022-4144 patch is not fully + adapted + +The https://gitee.com/openeuler/qemu/pulls/394 patch is used to fix CVE-2022-4144. +The QEMU version is as follows: 6. 2. The patch is installed normally. +When the patch is deployed to version 4.1.0, the OpenEuler patch is not fully adapted. + +The qxl_phys2virt function prototype is defined in the hw/display/qxl.c +file. + +void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id, + size_t size); + +Signed-off-by: liuhaipeng 00050065 +--- + hw/display/qxl.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index 5a923d30de..3442e66dcd 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -674,7 +674,8 @@ static int interface_get_command(QXLInstance *sin, struct QXLCommandExt *ext) + * + * https://cgit.freedesktop.org/spice/win32/qxl-wddm-dod/commit/?id=f6e099db39e7d0787f294d5fd0dce328b5210faa + */ +- void *msg = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id); ++ void *msg = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id, ++ sizeof(void)); + if (msg != NULL && ( + msg < (void *)qxl->vga.vram_ptr || + msg > ((void *)qxl->vga.vram_ptr + qxl->vga.vram_size))) { +-- +2.27.0 + diff --git a/hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch b/hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d84b851d5ea2ed0edc645fff2fee6cf32846823 --- /dev/null +++ b/hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch @@ -0,0 +1,72 @@ +From c62b0b93c853fa4c132752f4e74a863cd94ea663 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 22 May 2023 11:10:11 +0200 +Subject: [PATCH] hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI + controller (CVE-2023-0330) + +We cannot use the generic reentrancy guard in the LSI code, so +we have to manually prevent endless reentrancy here. The problematic +lsi_execute_script() function has already a way to detect whether +too many instructions have been executed - we just have to slightly +change the logic here that it also takes into account if the function +has been called too often in a reentrant way. + +The code in fuzz-lsi53c895a-test.c has been taken from an earlier +patch by Mauro Matteo Cascella. + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1563 +Message-Id: <20230522091011.1082574-1-thuth@redhat.com> +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Alexander Bulekov +Signed-off-by: Thomas Huth +--- + hw/scsi/lsi53c895a.c | 23 +++++++++++++++++------ + 1 file changed, 17 insertions(+), 6 deletions(-) + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index 88bccf2b4c..299e021fa1 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -1133,15 +1133,24 @@ static void lsi_execute_script(LSIState *s) + uint32_t addr, addr_high; + int opcode; + int insn_processed = 0; ++ static int reentrancy_level; ++ ++ reentrancy_level++; + + s->istat1 |= LSI_ISTAT1_SRUN; + again: +- if (++insn_processed > LSI_MAX_INSN) { +- /* Some windows drivers make the device spin waiting for a memory +- location to change. If we have been executed a lot of code then +- assume this is the case and force an unexpected device disconnect. +- This is apparently sufficient to beat the drivers into submission. +- */ ++ /* ++ * Some windows drivers make the device spin waiting for a memory location ++ * to change. If we have executed more than LSI_MAX_INSN instructions then ++ * assume this is the case and force an unexpected device disconnect. This ++ * is apparently sufficient to beat the drivers into submission. ++ * ++ * Another issue (CVE-2023-0330) can occur if the script is programmed to ++ * trigger itself again and again. Avoid this problem by stopping after ++ * being called multiple times in a reentrant way (8 is an arbitrary value ++ * which should be enough for all valid use cases). ++ */ ++ if (++insn_processed > LSI_MAX_INSN || reentrancy_level > 8) { + if (!(s->sien0 & LSI_SIST0_UDC)) { + qemu_log_mask(LOG_GUEST_ERROR, + "lsi_scsi: inf. loop with UDC masked"); +@@ -1595,6 +1604,8 @@ again: + } + } + trace_lsi_execute_script_stop(); ++ ++ reentrancy_level--; + } + + static uint8_t lsi_reg_readb(LSIState *s, int offset) +-- +2.27.0 + diff --git a/hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch b/hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch new file mode 100644 index 0000000000000000000000000000000000000000..1f740315cdb5b49fde710227fceba4face2a98fe --- /dev/null +++ b/hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch @@ -0,0 +1,39 @@ +From bb0ce0d474248dd3a204b7ce640ec2dfb1009f48 Mon Sep 17 00:00:00 2001 +From: Sven Schnelle +Date: Sun, 28 Jan 2024 21:22:14 +0100 +Subject: [PATCH] hw/scsi/lsi53c895a: add missing decrement of reentrancy + counter + +When the maximum count of SCRIPTS instructions is reached, the code +stops execution and returns, but fails to decrement the reentrancy +counter. This effectively renders the SCSI controller unusable +because on next entry the reentrancy counter is still above the limit. + +This bug was seen on HP-UX 10.20 which seems to trigger SCRIPTS +loops. + +Fixes: b987718bbb ("hw/scsi/lsi53c895a: Fix reentrancy issues in the LSI controller (CVE-2023-0330)") +Signed-off-by: Sven Schnelle +Message-ID: <20240128202214.2644768-1-svens@stackframe.org> +Reviewed-by: Thomas Huth +Tested-by: Helge Deller +Signed-off-by: Thomas Huth +--- + hw/scsi/lsi53c895a.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c +index 299e021fa1..336923be1c 100644 +--- a/hw/scsi/lsi53c895a.c ++++ b/hw/scsi/lsi53c895a.c +@@ -1158,6 +1158,7 @@ again: + lsi_script_scsi_interrupt(s, LSI_SIST0_UDC, 0); + lsi_disconnect(s); + trace_lsi_execute_script_stop(); ++ reentrancy_level--; + return; + } + insn = read_dword(s, s->dsp); +-- +2.27.0 + diff --git a/memory-prevent-dma-reentracy-issues.patch b/memory-prevent-dma-reentracy-issues.patch new file mode 100644 index 0000000000000000000000000000000000000000..a2d648f9ddd56cf38fe8bb2711f2c5b20420b082 --- /dev/null +++ b/memory-prevent-dma-reentracy-issues.patch @@ -0,0 +1,145 @@ +From 29ac6625503f6815f8223f4f8034041e26abd5be Mon Sep 17 00:00:00 2001 +From: Alexander Bulekov +Date: Thu, 27 Apr 2023 17:10:06 -0400 +Subject: [PATCH] memory: prevent dma-reentracy issues + +Add a flag to the DeviceState, when a device is engaged in PIO/MMIO/DMA. +This flag is set/checked prior to calling a device's MemoryRegion +handlers, and set when device code initiates DMA. The purpose of this +flag is to prevent two types of DMA-based reentrancy issues: + +1.) mmio -> dma -> mmio case +2.) bh -> dma write -> mmio case + +These issues have led to problems such as stack-exhaustion and +use-after-frees. + +Summary of the problem from Peter Maydell: +https://lore.kernel.org/qemu-devel/CAFEAcA_23vc7hE3iaM-JVA6W38LK4hJoWae5KcknhPRD5fPBZA@mail.gmail.com + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/62 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/540 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/541 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/556 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/557 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/827 +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1282 +Resolves: CVE-2023-0330 + +Signed-off-by: Alexander Bulekov +Reviewed-by: Thomas Huth +Message-Id: <20230427211013.2994127-2-alxndr@bu.edu> +[thuth: Replace warn_report() with warn_report_once()] +Signed-off-by: Thomas Huth +Signed-off-by: liuxiangdong +--- + include/exec/memory.h | 5 +++++ + include/hw/qdev-core.h | 7 +++++++ + include/net/net.h | 1 + + memory.c | 16 ++++++++++++++++ + 4 files changed, 29 insertions(+) + +diff --git a/include/exec/memory.h b/include/exec/memory.h +index dca8184277..ad260ebbd6 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -365,6 +365,8 @@ struct MemoryRegion { + bool is_iommu; + RAMBlock *ram_block; + Object *owner; ++ /* owner as TYPE_DEVICE. Used for re-entrancy checks in MR access hotpath */ ++ DeviceState *dev; + + const MemoryRegionOps *ops; + void *opaque; +@@ -387,6 +389,9 @@ struct MemoryRegion { + const char *name; + unsigned ioeventfd_nb; + MemoryRegionIoeventfd *ioeventfds; ++ ++ /* For devices designed to perform re-entrant IO into their own IO MRs */ ++ bool disable_reentrancy_guard; + }; + + struct IOMMUMemoryRegion { +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 136df7774c..364771f3a2 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -129,6 +129,10 @@ struct NamedGPIOList { + QLIST_ENTRY(NamedGPIOList) node; + }; + ++typedef struct { ++ bool engaged_in_io; ++} MemReentrancyGuard; ++ + /** + * DeviceState: + * @realized: Indicates whether the device has been fully constructed. +@@ -153,6 +157,9 @@ struct DeviceState { + int num_child_bus; + int instance_id_alias; + int alias_required_for_version; ++ ++ /* Is the device currently in mmio/pio/dma? Used to prevent re-entrancy */ ++ MemReentrancyGuard mem_reentrancy_guard; + }; + + struct DeviceListener { +diff --git a/include/net/net.h b/include/net/net.h +index 5609b2ecba..8a362e7279 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -5,6 +5,7 @@ + #include "qapi/qapi-types-net.h" + #include "net/queue.h" + #include "migration/vmstate.h" ++#include "hw/qdev-core.h" + + #define MAC_FMT "%02X:%02X:%02X:%02X:%02X:%02X" + #define MAC_ARG(x) ((uint8_t *)(x))[0], ((uint8_t *)(x))[1], \ +diff --git a/memory.c b/memory.c +index 5d8c9a9234..fa7053f9cb 100644 +--- a/memory.c ++++ b/memory.c +@@ -561,6 +561,18 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, + access_size_max = 4; + } + ++ /* Do not allow more than one simultaneous access to a device's IO Regions */ ++ if (mr->dev && !mr->disable_reentrancy_guard && ++ !mr->ram_device && !mr->ram && !mr->rom_device && !mr->readonly) { ++ if (mr->dev->mem_reentrancy_guard.engaged_in_io) { ++ warn_report_once("Blocked re-entrant IO on MemoryRegion: " ++ "%s at addr: 0x%" HWADDR_PRIX, ++ memory_region_name(mr), addr); ++ return MEMTX_ACCESS_ERROR; ++ } ++ mr->dev->mem_reentrancy_guard.engaged_in_io = true; ++ } ++ + /* FIXME: support unaligned access? */ + access_size = MAX(MIN(size, access_size_max), access_size_min); + access_mask = MAKE_64BIT_MASK(0, access_size * 8); +@@ -575,6 +587,9 @@ static MemTxResult access_with_adjusted_size(hwaddr addr, + access_mask, attrs); + } + } ++ if (mr->dev) { ++ mr->dev->mem_reentrancy_guard.engaged_in_io = false; ++ } + return r; + } + +@@ -1155,6 +1170,7 @@ static void memory_region_do_init(MemoryRegion *mr, + } + mr->name = g_strdup(name); + mr->owner = owner; ++ mr->dev = (DeviceState *) object_dynamic_cast(mr->owner, TYPE_DEVICE); + mr->ram_block = NULL; + + if (name) { +-- +2.27.0 + diff --git a/net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch b/net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch new file mode 100644 index 0000000000000000000000000000000000000000..f87f541df0e708d0941756cf819861b00e2f7978 --- /dev/null +++ b/net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch @@ -0,0 +1,530 @@ +From 021760e395e362ae5edad6b3930e88b795b1f0f9 Mon Sep 17 00:00:00 2001 +From: Akihiko Odaki +Date: Thu, 1 Jun 2023 12:18:58 +0900 +Subject: [PATCH] net: Provide MemReentrancyGuard * to qemu_new_nic() + +Recently MemReentrancyGuard was added to DeviceState to record that the +device is engaging in I/O. The network device backend needs to update it +when delivering a packet to a device. + +In preparation for such a change, add MemReentrancyGuard * as a +parameter of qemu_new_nic(). + +Signed-off-by: Akihiko Odaki +Reviewed-by: Alexander Bulekov +Signed-off-by: Jason Wang +--- + hw/arm/musicpal.c | 3 ++- + hw/net/allwinner_emac.c | 3 ++- + hw/net/cadence_gem.c | 3 ++- + hw/net/dp8393x.c | 3 ++- + hw/net/e1000.c | 3 ++- + hw/net/e1000e.c | 2 +- + hw/net/eepro100.c | 4 +++- + hw/net/etraxfs_eth.c | 3 ++- + hw/net/fsl_etsec/etsec.c | 3 ++- + hw/net/ftgmac100.c | 4 ++-- + hw/net/imx_fec.c | 2 +- + hw/net/lan9118.c | 3 ++- + hw/net/mcf_fec.c | 3 ++- + hw/net/mipsnet.c | 3 ++- + hw/net/ne2000-isa.c | 3 ++- + hw/net/ne2000-pci.c | 3 ++- + hw/net/opencores_eth.c | 3 ++- + hw/net/pcnet.c | 3 ++- + hw/net/rocker/rocker_fp.c | 4 ++-- + hw/net/rtl8139.c | 3 ++- + hw/net/smc91c111.c | 3 ++- + hw/net/spapr_llan.c | 3 ++- + hw/net/stellaris_enet.c | 3 ++- + hw/net/sungem.c | 2 +- + hw/net/sunhme.c | 3 ++- + hw/net/virtio-net.c | 6 ++++-- + hw/net/vmxnet3.c | 2 +- + hw/net/xen_nic.c | 2 +- + hw/net/xgmac.c | 3 ++- + hw/net/xilinx_axienet.c | 3 ++- + hw/net/xilinx_ethlite.c | 3 ++- + hw/usb/dev-network.c | 3 ++- + include/net/net.h | 1 + + net/net.c | 1 + + 34 files changed, 64 insertions(+), 35 deletions(-) + +diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c +index 95d56f3208..83d8ea9952 100644 +--- a/hw/arm/musicpal.c ++++ b/hw/arm/musicpal.c +@@ -400,7 +400,8 @@ static void mv88w8618_eth_realize(DeviceState *dev, Error **errp) + mv88w8618_eth_state *s = MV88W8618_ETH(dev); + + s->nic = qemu_new_nic(&net_mv88w8618_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + } + + static const VMStateDescription mv88w8618_eth_vmsd = { +diff --git a/hw/net/allwinner_emac.c b/hw/net/allwinner_emac.c +index eecda52800..2475df7883 100644 +--- a/hw/net/allwinner_emac.c ++++ b/hw/net/allwinner_emac.c +@@ -450,7 +450,8 @@ static void aw_emac_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_aw_emac_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + fifo8_create(&s->rx_fifo, RX_FIFO_SIZE); +diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c +index 52205f36be..5c99ce3b0f 100644 +--- a/hw/net/cadence_gem.c ++++ b/hw/net/cadence_gem.c +@@ -1565,7 +1565,8 @@ static void gem_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_gem_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + } + + static void gem_init(Object *obj) +diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c +index a64da76bf3..69a8097a68 100644 +--- a/hw/net/dp8393x.c ++++ b/hw/net/dp8393x.c +@@ -881,7 +881,8 @@ static void dp8393x_realize(DeviceState *dev, Error **errp) + "dp8393x-regs", 0x40 << s->it_shift); + + s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s); +diff --git a/hw/net/e1000.c b/hw/net/e1000.c +index a41b5b116d..4daa7a47cd 100644 +--- a/hw/net/e1000.c ++++ b/hw/net/e1000.c +@@ -1719,7 +1719,8 @@ static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) + macaddr); + + d->nic = qemu_new_nic(&net_e1000_info, &d->conf, +- object_get_typename(OBJECT(d)), dev->id, d); ++ object_get_typename(OBJECT(d)), dev->id, ++ &dev->mem_reentrancy_guard, d); + + qemu_format_nic_info_str(qemu_get_queue(d->nic), macaddr); + +diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c +index 581f7d03d5..1380917100 100644 +--- a/hw/net/e1000e.c ++++ b/hw/net/e1000e.c +@@ -323,7 +323,7 @@ e1000e_init_net_peer(E1000EState *s, PCIDevice *pci_dev, uint8_t *macaddr) + int i; + + s->nic = qemu_new_nic(&net_e1000e_info, &s->conf, +- object_get_typename(OBJECT(s)), dev->id, s); ++ object_get_typename(OBJECT(s)), dev->id, &dev->mem_reentrancy_guard, s); + + s->core.max_queue_num = s->conf.peers.queues - 1; + +diff --git a/hw/net/eepro100.c b/hw/net/eepro100.c +index 6607c9142d..ed1a7f54f0 100644 +--- a/hw/net/eepro100.c ++++ b/hw/net/eepro100.c +@@ -1863,7 +1863,9 @@ static void e100_nic_realize(PCIDevice *pci_dev, Error **errp) + nic_reset(s); + + s->nic = qemu_new_nic(&net_eepro100_info, &s->conf, +- object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s); ++ object_get_typename(OBJECT(pci_dev)), ++ pci_dev->qdev.id, ++ &pci_dev->qdev.mem_reentrancy_guard, s); + + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + TRACE(OTHER, logout("%s\n", qemu_get_queue(s->nic)->info_str)); +diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c +index 4cfbf1135a..af7cfb7861 100644 +--- a/hw/net/etraxfs_eth.c ++++ b/hw/net/etraxfs_eth.c +@@ -625,7 +625,8 @@ static void etraxfs_eth_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, +- object_get_typename(OBJECT(s)), dev->id, s); ++ object_get_typename(OBJECT(s)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->phy.read = tdk_read; +diff --git a/hw/net/fsl_etsec/etsec.c b/hw/net/fsl_etsec/etsec.c +index 2a8b99a2e4..d59e757d3b 100644 +--- a/hw/net/fsl_etsec/etsec.c ++++ b/hw/net/fsl_etsec/etsec.c +@@ -386,7 +386,8 @@ static void etsec_realize(DeviceState *dev, Error **errp) + eTSEC *etsec = ETSEC_COMMON(dev); + + etsec->nic = qemu_new_nic(&net_etsec_info, &etsec->conf, +- object_get_typename(OBJECT(dev)), dev->id, etsec); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, etsec); + qemu_format_nic_info_str(qemu_get_queue(etsec->nic), etsec->conf.macaddr.a); + + +diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c +index d2cded5e94..aad090b18a 100644 +--- a/hw/net/ftgmac100.c ++++ b/hw/net/ftgmac100.c +@@ -1018,8 +1018,8 @@ static void ftgmac100_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf, +- object_get_typename(OBJECT(dev)), DEVICE(dev)->id, +- s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c +index 404154ebbf..18fcbb743a 100644 +--- a/hw/net/imx_fec.c ++++ b/hw/net/imx_fec.c +@@ -1313,7 +1313,7 @@ static void imx_eth_realize(DeviceState *dev, Error **errp) + + s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf, + object_get_typename(OBJECT(dev)), +- DEVICE(dev)->id, s); ++ DEVICE(dev)->id, &dev->mem_reentrancy_guard, s); + + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } +diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c +index f1a1d2351e..c47e36790b 100644 +--- a/hw/net/lan9118.c ++++ b/hw/net/lan9118.c +@@ -1336,7 +1336,8 @@ static void lan9118_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_lan9118_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + s->eeprom[0] = 0xa5; + for (i = 0; i < 6; i++) { +diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c +index 78468fad6b..876cef0fd0 100644 +--- a/hw/net/mcf_fec.c ++++ b/hw/net/mcf_fec.c +@@ -638,7 +638,8 @@ static void mcf_fec_realize(DeviceState *dev, Error **errp) + mcf_fec_state *s = MCF_FEC_NET(dev); + + s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/mipsnet.c b/hw/net/mipsnet.c +index c5fbd8431f..9f9eea7fcc 100644 +--- a/hw/net/mipsnet.c ++++ b/hw/net/mipsnet.c +@@ -248,7 +248,8 @@ static void mipsnet_realize(DeviceState *dev, Error **errp) + sysbus_init_irq(sbd, &s->irq); + + s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/ne2000-isa.c b/hw/net/ne2000-isa.c +index 3490e54c5a..1b016bb53b 100644 +--- a/hw/net/ne2000-isa.c ++++ b/hw/net/ne2000-isa.c +@@ -73,7 +73,8 @@ static void isa_ne2000_realizefn(DeviceState *dev, Error **errp) + ne2000_reset(s); + + s->nic = qemu_new_nic(&net_ne2000_isa_info, &s->c, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); + } + +diff --git a/hw/net/ne2000-pci.c b/hw/net/ne2000-pci.c +index cb05744f3c..844f43f409 100644 +--- a/hw/net/ne2000-pci.c ++++ b/hw/net/ne2000-pci.c +@@ -67,7 +67,8 @@ static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp) + + s->nic = qemu_new_nic(&net_ne2000_info, &s->c, + object_get_typename(OBJECT(pci_dev)), +- pci_dev->qdev.id, s); ++ pci_dev->qdev.id, ++ &pci_dev->qdev.mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); + } + +diff --git a/hw/net/opencores_eth.c b/hw/net/opencores_eth.c +index a5abb8df46..3fde629df5 100644 +--- a/hw/net/opencores_eth.c ++++ b/hw/net/opencores_eth.c +@@ -732,7 +732,8 @@ static void sysbus_open_eth_realize(DeviceState *dev, Error **errp) + sysbus_init_irq(sbd, &s->irq); + + s->nic = qemu_new_nic(&net_open_eth_info, &s->conf, +- object_get_typename(OBJECT(s)), dev->id, s); ++ object_get_typename(OBJECT(s)), dev->id, ++ &dev->mem_reentrancy_guard, s); + } + + static void qdev_open_eth_reset(DeviceState *dev) +diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c +index 9e8d267536..0ba54a23bf 100644 +--- a/hw/net/pcnet.c ++++ b/hw/net/pcnet.c +@@ -1717,7 +1717,8 @@ void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info) + s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s); + + qemu_macaddr_default_if_unset(&s->conf.macaddr); +- s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s); ++ s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), ++ dev->id, &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + /* Initialize the PROM */ +diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c +index 4aa7da79b8..0cd3534fd0 100644 +--- a/hw/net/rocker/rocker_fp.c ++++ b/hw/net/rocker/rocker_fp.c +@@ -238,8 +238,8 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name, + port->conf.bootindex = -1; + port->conf.peers = *peers; + +- port->nic = qemu_new_nic(&fp_port_info, &port->conf, +- sw_name, NULL, port); ++ port->nic = qemu_new_nic(&fp_port_info, &port->conf, sw_name, NULL, ++ &DEVICE(r)->mem_reentrancy_guard, port); + qemu_format_nic_info_str(qemu_get_queue(port->nic), + port->conf.macaddr.a); + +diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c +index 79584fbb17..2ed69e5006 100644 +--- a/hw/net/rtl8139.c ++++ b/hw/net/rtl8139.c +@@ -3396,7 +3396,8 @@ static void pci_rtl8139_realize(PCIDevice *dev, Error **errp) + s->eeprom.contents[9] = s->conf.macaddr.a[4] | s->conf.macaddr.a[5] << 8; + + s->nic = qemu_new_nic(&net_rtl8139_info, &s->conf, +- object_get_typename(OBJECT(dev)), d->id, s); ++ object_get_typename(OBJECT(dev)), d->id, ++ &d->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->cplus_txbuffer = NULL; +diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c +index 4a612eebe9..8f7b254218 100644 +--- a/hw/net/smc91c111.c ++++ b/hw/net/smc91c111.c +@@ -778,7 +778,8 @@ static void smc91c111_realize(DeviceState *dev, Error **errp) + sysbus_init_irq(sbd, &s->irq); + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + /* ??? Save/restore. */ + } +diff --git a/hw/net/spapr_llan.c b/hw/net/spapr_llan.c +index f162d49025..2adf6c840e 100644 +--- a/hw/net/spapr_llan.c ++++ b/hw/net/spapr_llan.c +@@ -326,7 +326,8 @@ static void spapr_vlan_realize(SpaprVioDevice *sdev, Error **errp) + memcpy(&dev->perm_mac.a, &dev->nicconf.macaddr.a, sizeof(dev->perm_mac.a)); + + dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf, +- object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev); ++ object_get_typename(OBJECT(sdev)), sdev->qdev.id, ++ &sdev->qdev.mem_reentrancy_guard, dev); + qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a); + + dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue, +diff --git a/hw/net/stellaris_enet.c b/hw/net/stellaris_enet.c +index 2f645bfb71..89772249bc 100644 +--- a/hw/net/stellaris_enet.c ++++ b/hw/net/stellaris_enet.c +@@ -489,7 +489,8 @@ static void stellaris_enet_realize(DeviceState *dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + + s->nic = qemu_new_nic(&net_stellaris_enet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/sungem.c b/hw/net/sungem.c +index 37b62f62b8..40c8c4e6f5 100644 +--- a/hw/net/sungem.c ++++ b/hw/net/sungem.c +@@ -1358,7 +1358,7 @@ static void sungem_realize(PCIDevice *pci_dev, Error **errp) + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_sungem_info, &s->conf, + object_get_typename(OBJECT(dev)), +- dev->id, s); ++ dev->id, &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), + s->conf.macaddr.a); + } +diff --git a/hw/net/sunhme.c b/hw/net/sunhme.c +index 8b8603e696..79f4716c75 100644 +--- a/hw/net/sunhme.c ++++ b/hw/net/sunhme.c +@@ -890,7 +890,8 @@ static void sunhme_realize(PCIDevice *pci_dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_sunhme_info, &s->conf, +- object_get_typename(OBJECT(d)), d->id, s); ++ object_get_typename(OBJECT(d)), d->id, ++ &d->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 28e9cd52ff..b7fc688b4f 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -2774,10 +2774,12 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) + * Happen when virtio_net_set_netclient_name has been called. + */ + n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, +- n->netclient_type, n->netclient_name, n); ++ n->netclient_type, n->netclient_name, ++ &dev->mem_reentrancy_guard, n); + } else { + n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf, +- object_get_typename(OBJECT(dev)), dev->id, n); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, n); + } + + peer_test_vnet_hdr(n); +diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c +index ecc4f5bcf0..1a6eff7d87 100644 +--- a/hw/net/vmxnet3.c ++++ b/hw/net/vmxnet3.c +@@ -2062,7 +2062,7 @@ static void vmxnet3_net_init(VMXNET3State *s) + + s->nic = qemu_new_nic(&net_vmxnet3_info, &s->conf, + object_get_typename(OBJECT(s)), +- d->id, s); ++ d->id, &d->mem_reentrancy_guard, s); + + s->peer_has_vhdr = vmxnet3_peer_has_vnet_hdr(s); + s->tx_sop = true; +diff --git a/hw/net/xen_nic.c b/hw/net/xen_nic.c +index ffb3b5898d..cf0427e3e6 100644 +--- a/hw/net/xen_nic.c ++++ b/hw/net/xen_nic.c +@@ -295,7 +295,7 @@ static int net_init(struct XenLegacyDevice *xendev) + } + + netdev->nic = qemu_new_nic(&net_xen_info, &netdev->conf, +- "xen", NULL, netdev); ++ "xen", NULL, &xendev->qdev.mem_reentrancy_guard, netdev); + + snprintf(qemu_get_queue(netdev->nic)->info_str, + sizeof(qemu_get_queue(netdev->nic)->info_str), +diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c +index f496f7ed4c..91c98029c8 100644 +--- a/hw/net/xgmac.c ++++ b/hw/net/xgmac.c +@@ -399,7 +399,8 @@ static void xgmac_enet_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) | +diff --git a/hw/net/xilinx_axienet.c b/hw/net/xilinx_axienet.c +index feeaca680e..3139f030d6 100644 +--- a/hw/net/xilinx_axienet.c ++++ b/hw/net/xilinx_axienet.c +@@ -970,7 +970,8 @@ static void xilinx_enet_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_xilinx_enet_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + + tdk_init(&s->TEMAC.phy); +diff --git a/hw/net/xilinx_ethlite.c b/hw/net/xilinx_ethlite.c +index 8f3a8f8597..e927e6563f 100644 +--- a/hw/net/xilinx_ethlite.c ++++ b/hw/net/xilinx_ethlite.c +@@ -233,7 +233,8 @@ static void xilinx_ethlite_realize(DeviceState *dev, Error **errp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf, +- object_get_typename(OBJECT(dev)), dev->id, s); ++ object_get_typename(OBJECT(dev)), dev->id, ++ &dev->mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + } + +diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c +index 889069dd5a..3b695193d6 100644 +--- a/hw/usb/dev-network.c ++++ b/hw/usb/dev-network.c +@@ -1359,7 +1359,8 @@ static void usb_net_realize(USBDevice *dev, Error **errrp) + + qemu_macaddr_default_if_unset(&s->conf.macaddr); + s->nic = qemu_new_nic(&net_usbnet_info, &s->conf, +- object_get_typename(OBJECT(s)), s->dev.qdev.id, s); ++ object_get_typename(OBJECT(s)), s->dev.qdev.id, ++ &s->dev.qdev.mem_reentrancy_guard, s); + qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); + snprintf(s->usbstring_mac, sizeof(s->usbstring_mac), + "%02x%02x%02x%02x%02x%02x", +diff --git a/include/net/net.h b/include/net/net.h +index 8a362e7279..d5edacf75a 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -135,6 +135,7 @@ NICState *qemu_new_nic(NetClientInfo *info, + NICConf *conf, + const char *model, + const char *name, ++ MemReentrancyGuard *reentrancy_guard, + void *opaque); + void qemu_del_nic(NICState *nic); + NetClientState *qemu_get_subqueue(NICState *nic, int queue_index); +diff --git a/net/net.c b/net/net.c +index 3b5631879c..20e6a6c4b2 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -276,6 +276,7 @@ NICState *qemu_new_nic(NetClientInfo *info, + NICConf *conf, + const char *model, + const char *name, ++ MemReentrancyGuard *reentrancy_guard, + void *opaque) + { + NetClientState **peers = conf->peers.ncs; +-- +2.27.0 + diff --git a/net-Update-MemReentrancyGuard-for-NIC.patch b/net-Update-MemReentrancyGuard-for-NIC.patch new file mode 100644 index 0000000000000000000000000000000000000000..a02d1b3c849ed838d4dd67898b72f61b34280eb6 --- /dev/null +++ b/net-Update-MemReentrancyGuard-for-NIC.patch @@ -0,0 +1,85 @@ +From dace1058db6e82e5105578d4238ad899e6999965 Mon Sep 17 00:00:00 2001 +From: Akihiko Odaki +Date: Thu, 1 Jun 2023 12:18:59 +0900 +Subject: [PATCH] net: Update MemReentrancyGuard for NIC + +Recently MemReentrancyGuard was added to DeviceState to record that the +device is engaging in I/O. The network device backend needs to update it +when delivering a packet to a device. + +This implementation follows what bottom half does, but it does not add +a tracepoint for the case that the network device backend started +delivering a packet to a device which is already engaging in I/O. This +is because such reentrancy frequently happens for +qemu_flush_queued_packets() and is insignificant. + +Fixes: CVE-2023-3019 +Reported-by: Alexander Bulekov +Signed-off-by: Akihiko Odaki +Acked-by: Alexander Bulekov +Signed-off-by: Jason Wang +--- + include/net/net.h | 1 + + net/net.c | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + +diff --git a/include/net/net.h b/include/net/net.h +index d5edacf75a..d6533febd3 100644 +--- a/include/net/net.h ++++ b/include/net/net.h +@@ -106,6 +106,7 @@ struct NetClientState { + typedef struct NICState { + NetClientState *ncs; + NICConf *conf; ++ MemReentrancyGuard *reentrancy_guard; + void *opaque; + bool peer_deleted; + } NICState; +diff --git a/net/net.c b/net/net.c +index 20e6a6c4b2..97b20044f9 100644 +--- a/net/net.c ++++ b/net/net.c +@@ -289,6 +289,7 @@ NICState *qemu_new_nic(NetClientInfo *info, + nic = g_malloc0(info->size + sizeof(NetClientState) * queues); + nic->ncs = (void *)nic + info->size; + nic->conf = conf; ++ nic->reentrancy_guard = reentrancy_guard, + nic->opaque = opaque; + + for (i = 0; i < queues; i++) { +@@ -733,6 +734,7 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, + int iovcnt, + void *opaque) + { ++ MemReentrancyGuard *owned_reentrancy_guard; + NetClientState *nc = opaque; + int ret; + +@@ -745,12 +747,24 @@ static ssize_t qemu_deliver_packet_iov(NetClientState *sender, + return 0; + } + ++ if (nc->info->type != NET_CLIENT_DRIVER_NIC || ++ qemu_get_nic(nc)->reentrancy_guard->engaged_in_io) { ++ owned_reentrancy_guard = NULL; ++ } else { ++ owned_reentrancy_guard = qemu_get_nic(nc)->reentrancy_guard; ++ owned_reentrancy_guard->engaged_in_io = true; ++ } ++ + if (nc->info->receive_iov && !(flags & QEMU_NET_PACKET_FLAG_RAW)) { + ret = nc->info->receive_iov(nc, iov, iovcnt); + } else { + ret = nc_sendv_compat(nc, iov, iovcnt, flags); + } + ++ if (owned_reentrancy_guard) { ++ owned_reentrancy_guard->engaged_in_io = false; ++ } ++ + if (ret == 0) { + nc->receive_disabled = 1; + } +-- +2.27.0 + diff --git a/qemu.spec b/qemu.spec index 0384bc032d831385cc7630bfadc8884ae15a916b..16cb7327924ccb2ab7c1dd6fbccca036fe57ee2a 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,6 +1,6 @@ Name: qemu Version: 4.1.0 -Release: 77 +Release: 78 Epoch: 10 Summary: QEMU is a generic and open source machine emulator and virtualizer License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 @@ -356,6 +356,14 @@ Patch0343: io-remove-io-watch-if-TLS-channel-is-closed-during-h.patch Patch0344: pci-assert-configuration-access-is-within-bounds.patch Patch0345: accel-tcg-fix-race-in-cpu_exec_step_atomic-bug-18630.patch Patch0346: hw-pvrdma-Protect-against-buggy-or-malicious-guest-driver.patch +Patch0347: target-arm-fix-typo-in-cpu.h-ID_AA64PFR1-field-name.patch +Patch0348: Fixed-the-early-version-of-CVE-2022-4144-patch-is-no.patch +Patch0349: softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch +Patch0350: memory-prevent-dma-reentracy-issues.patch +Patch0351: net-Provide-MemReentrancyGuard-to-qemu_new_nic.patch +Patch0352: net-Update-MemReentrancyGuard-for-NIC.patch +Patch0353: hw-scsi-lsi53c895a-Fix-reentrancy-issues-in-the-LSI-.patch +Patch0354: hw-scsi-lsi53c895a-add-missing-decrement-of-reentran.patch BuildRequires: flex BuildRequires: bison @@ -757,6 +765,16 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Sat Mar 9 2024 Jiabo Feng +- 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 +- net: Provide MemReentrancyGuard * to qemu_new_nic() +- memory: prevent dma-reentracy issues +- softmmu/physmem: Introduce MemTxAttrs::memory field and MEMTX_ACCESS_ERROR +- Fixed the early version of CVE-2022-4144 patch is not fully adapted +- target/arm: fix typo in cpu.h ID_AA64PFR1 field name + * Tue Nov 28 2023 Jiabo Feng - hw/pvrdma: Protect against buggy or malicious guest driver diff --git a/softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch b/softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch new file mode 100644 index 0000000000000000000000000000000000000000..f358ed489b4fc30fae1c5f1f8827fc91893bc415 --- /dev/null +++ b/softmmu-physmem-Introduce-MemTxAttrs-memory-field-an.patch @@ -0,0 +1,151 @@ +From dc76761d585b66e5c15a7427b090d059a4467831 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 15 Dec 2021 19:24:21 +0100 +Subject: [PATCH] softmmu/physmem: Introduce MemTxAttrs::memory field and + MEMTX_ACCESS_ERROR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Add the 'memory' bit to the memory attributes to restrict bus +controller accesses to memories. + +Introduce flatview_access_allowed() to check bus permission +before running any bus transaction. + +Have read/write accessors return MEMTX_ACCESS_ERROR if an access is +restricted. + +There is no change for the default case where 'memory' is not set. + +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20211215182421.418374-4-philmd@redhat.com> +Reviewed-by: Richard Henderson +Reviewed-by: Stefan Hajnoczi +[thuth: Replaced MEMTX_BUS_ERROR with MEMTX_ACCESS_ERROR, remove "inline"] +Signed-off-by: Thomas Huth +--- + exec.c | 44 +++++++++++++++++++++++++++++++++++++++-- + include/exec/memattrs.h | 9 +++++++++ + 2 files changed, 51 insertions(+), 2 deletions(-) + +diff --git a/exec.c b/exec.c +index e785178d73..0a6ac67c84 100644 +--- a/exec.c ++++ b/exec.c +@@ -43,6 +43,7 @@ + #include "qemu.h" + #else /* !CONFIG_USER_ONLY */ + #include "hw/hw.h" ++#include "qemu/log.h" + #include "exec/memory.h" + #include "exec/ioport.h" + #include "sysemu/dma.h" +@@ -3326,6 +3327,33 @@ static bool prepare_mmio_access(MemoryRegion *mr) + return release_lock; + } + ++/** ++ * flatview_access_allowed ++ * @mr: #MemoryRegion to be accessed ++ * @attrs: memory transaction attributes ++ * @addr: address within that memory region ++ * @len: the number of bytes to access ++ * ++ * Check if a memory transaction is allowed. ++ * ++ * Returns: true if transaction is allowed, false if denied. ++ */ ++static bool flatview_access_allowed(MemoryRegion *mr, MemTxAttrs attrs, ++ hwaddr addr, hwaddr len) ++{ ++ if (likely(!attrs.memory)) { ++ return true; ++ } ++ if (memory_region_is_ram(mr)) { ++ return true; ++ } ++ qemu_log_mask(LOG_GUEST_ERROR, ++ "Invalid access to non-RAM device at " ++ "addr 0x%" HWADDR_PRIX ", size %" HWADDR_PRIu ", " ++ "region '%s'\n", addr, len, memory_region_name(mr)); ++ return false; ++} ++ + /* Called within RCU critical section. */ + static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr, + MemTxAttrs attrs, +@@ -3339,7 +3367,10 @@ static MemTxResult flatview_write_continue(FlatView *fv, hwaddr addr, + bool release_lock = false; + + for (;;) { +- if (!memory_access_is_direct(mr, true)) { ++ if (!flatview_access_allowed(mr, attrs, addr1, l)) { ++ result |= MEMTX_ACCESS_ERROR; ++ /* Keep going. */ ++ } else if (!memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + l = memory_access_size(mr, l, addr1); + /* XXX: could force current_cpu to NULL to avoid +@@ -3384,6 +3415,9 @@ static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs, + + l = len; + mr = flatview_translate(fv, addr, &addr1, &l, true, attrs); ++ if (!flatview_access_allowed(mr, attrs, addr, len)) { ++ return MEMTX_ACCESS_ERROR; ++ } + result = flatview_write_continue(fv, addr, attrs, buf, len, + addr1, l, mr); + +@@ -3402,7 +3436,10 @@ MemTxResult flatview_read_continue(FlatView *fv, hwaddr addr, + bool release_lock = false; + + for (;;) { +- if (!memory_access_is_direct(mr, false)) { ++ if (!flatview_access_allowed(mr, attrs, addr1, l)) { ++ result |= MEMTX_ACCESS_ERROR; ++ /* Keep going. */ ++ } else if (!memory_access_is_direct(mr, false)) { + /* I/O case */ + release_lock |= prepare_mmio_access(mr); + l = memory_access_size(mr, l, addr1); +@@ -3444,6 +3481,9 @@ static MemTxResult flatview_read(FlatView *fv, hwaddr addr, + + l = len; + mr = flatview_translate(fv, addr, &addr1, &l, false, attrs); ++ if (!flatview_access_allowed(mr, attrs, addr, len)) { ++ return MEMTX_ACCESS_ERROR; ++ } + return flatview_read_continue(fv, addr, attrs, buf, len, + addr1, l, mr); + } +diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h +index d4a3477d71..570e73c06f 100644 +--- a/include/exec/memattrs.h ++++ b/include/exec/memattrs.h +@@ -35,6 +35,14 @@ typedef struct MemTxAttrs { + unsigned int secure:1; + /* Memory access is usermode (unprivileged) */ + unsigned int user:1; ++ /* ++ * Bus interconnect and peripherals can access anything (memories, ++ * devices) by default. By setting the 'memory' bit, bus transaction ++ * are restricted to "normal" memories (per the AMBA documentation) ++ * versus devices. Access to devices will be logged and rejected ++ * (see MEMTX_ACCESS_ERROR). ++ */ ++ unsigned int memory:1; + /* Requester ID (for MSI for example) */ + unsigned int requester_id:16; + /* +@@ -64,6 +72,7 @@ typedef struct MemTxAttrs { + #define MEMTX_OK 0 + #define MEMTX_ERROR (1U << 0) /* device returned an error */ + #define MEMTX_DECODE_ERROR (1U << 1) /* nothing at that address */ ++#define MEMTX_ACCESS_ERROR (1U << 2) /* access denied */ + typedef uint32_t MemTxResult; + + #endif +-- +2.27.0 + diff --git a/target-arm-fix-typo-in-cpu.h-ID_AA64PFR1-field-name.patch b/target-arm-fix-typo-in-cpu.h-ID_AA64PFR1-field-name.patch new file mode 100644 index 0000000000000000000000000000000000000000..eeefd61f7ea8b9373f4b4684f70a113ab3574f12 --- /dev/null +++ b/target-arm-fix-typo-in-cpu.h-ID_AA64PFR1-field-name.patch @@ -0,0 +1,50 @@ +From 39d5b33f496128583682721b5c857edc9bcc2ba2 Mon Sep 17 00:00:00 2001 +From: Leif Lindholm +Date: Fri, 8 Jan 2021 18:51:49 +0000 +Subject: [PATCH] target/arm: fix typo in cpu.h ID_AA64PFR1 field name +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +SBSS -> SSBS + +Signed-off-by: Leif Lindholm +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Peter Maydell +Reviewed-by: Laurent Desnogues +Message-id: 20210108185154.8108-2-leif@nuviainc.com +Signed-off-by: Peter Maydell +--- + target/arm/cpu.c | 2 +- + target/arm/cpu.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 3f62336acf..03ae7d4019 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -1223,7 +1223,7 @@ static struct CPUFeatureInfo cpu_features[] = { + FIELD_INFO("sve", ID_AA64PFR0, SVE, false, 1, 0, false), + + FIELD_INFO("bti", ID_AA64PFR1, BT, false, 1, 0, false), +- FIELD_INFO("sbss", ID_AA64PFR1, SBSS, false, 1, 0, false), ++ FIELD_INFO("ssbs", ID_AA64PFR1, SSBS, false, 1, 0, false), + FIELD_INFO("mte", ID_AA64PFR1, MTE, false, 1, 0, false), + FIELD_INFO("ras_frac", ID_AA64PFR1, RAS_FRAC, false, 1, 0, false), + +diff --git a/target/arm/cpu.h b/target/arm/cpu.h +index eb875e112a..8da92bd784 100644 +--- a/target/arm/cpu.h ++++ b/target/arm/cpu.h +@@ -1759,7 +1759,7 @@ FIELD(ID_AA64PFR0, CSV2, 56, 4) + FIELD(ID_AA64PFR0, CSV3, 60, 4) + + FIELD(ID_AA64PFR1, BT, 0, 4) +-FIELD(ID_AA64PFR1, SBSS, 4, 4) ++FIELD(ID_AA64PFR1, SSBS, 4, 4) + FIELD(ID_AA64PFR1, MTE, 8, 4) + FIELD(ID_AA64PFR1, RAS_FRAC, 12, 4) + FIELD(ID_AA64PFR1, MPAM_FRAC, 16, 4) +-- +2.27.0 +