Virtuozzo QEMU development (svt-core@virtuozzo.com)
 help / color / mirror / Atom feed
* [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666
@ 2026-10-26 11:46 Denis V. Lunev
  2026-10-26 11:46 ` [PATCH hci-8.1 1/3] hw/usb/hcd-xhci: Set reentrancy guard in timer functions (CVE-2026-17588) #VSTOR-151666 Denis V. Lunev
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Denis V. Lunev @ 2026-10-26 11:46 UTC (permalink / raw)
  To: andrey.drobyshev; +Cc: svt-core, den

A guest can crash QEMU through the emulated xHCI controller by pointing
the event ring, or an MSI-X vector, at the controller's own doorbell
register. An event posted outside MMIO context, such as a USB transfer
completion from the main loop, is then written by DMA into doorbell 0
and runs the command ring re-entrantly. A Disable Slot command planted
there frees the transfer and endpoint the caller still holds.

VSTOR-151666 is this crash on a production node: qemu-kvm SIGSEGV in
xhci_ep_free_xfer() <- xhci_complete() <- usb_msd_command_complete().
In the core, intr[0].er_start equals BAR0 + 0x2000, which is doorbell 0,
and most crashes of that VM follow the
"Blocked re-entrant IO on MemoryRegion: doorbell at addr: 0x0" warning
by a second or two.

Upstream fixed it with these three commits from Thomas Huth:

  f91b0544fe  engage the re-entrancy guard in the xHCI timer callbacks
              (CVE-2026-17588)
  89e653b773  restrict xHCI DMA writes to RAM, so events cannot reach
              MMIO at all
  cfa70f3a82  engage the guard in xhci_complete() and the other port
              callbacks (CVE-2026-111819); this is the path that crashed

All three cherry-pick cleanly onto hci-dev with no changes. The only
local edit is the #VSTOR-151666 tag in the subjects.

Upstream has no test for either CVE. hw/usb/hcd-xhci.c builds, and the
existing usb-hcd-xhci-test qtest passes. The attack itself has not been
reproduced.

The same series is needed on hci-8.0, hci-7.4 and hci-7.3 and will be
sent separately.

Signed-off-by: Denis V. Lunev <den@openvz.org>

Thomas Huth (3):
  hw/usb/hcd-xhci: Set reentrancy guard in timer functions
    (CVE-2026-17588) #VSTOR-151666
  hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666
  hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code
    #VSTOR-151666

 hw/usb/hcd-xhci.c | 52 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 47 insertions(+), 5 deletions(-)


base-commit: f3c1d9ef263edfab8d2a273078493bb766dcf8f8
-- 
2.53.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH hci-8.1 1/3] hw/usb/hcd-xhci: Set reentrancy guard in timer functions (CVE-2026-17588) #VSTOR-151666
  2026-10-26 11:46 [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Denis V. Lunev
@ 2026-10-26 11:46 ` Denis V. Lunev
  2026-10-26 11:51   ` no-reply
  2026-10-26 11:46 ` [PATCH hci-8.1 2/3] hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666 Denis V. Lunev
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Denis V. Lunev @ 2026-10-26 11:46 UTC (permalink / raw)
  To: andrey.drobyshev; +Cc: svt-core, den

From: Thomas Huth <thuth@redhat.com>

The xHCI controller processes USB events from timer callbacks
(xhci_mfwrap_timer and xhci_ep_kick_timer) outside of any MMIO handler
context. The device's mem_reentrancy_guard is therefore not engaged
during this processing.

A malicious guest can exploit this by pointing the event ring base
address (er_start) at the xHCI doorbell MMIO region. When
xhci_write_event() performs a DMA write to deliver a transfer
completion event, the write lands on doorbell register 0. If the
written value is 0, this triggers xhci_process_commands() reentrantly.
A CR_DISABLE_SLOT command prepared on the command ring then frees
endpoint and transfer objects via xhci_disable_ep() / g_free() while
the outer call stack still holds references to them, causing a
heap use-after-free.

Fix this by setting engaged_in_io on the device's mem_reentrancy_guard
around the processing in these non-MMIO entry points. This mirrors
the protection that EHCI, DWC2, and UHCI already have via
qemu_bh_new_guarded(). With the guard active, the memory subsystem's
automatic reentrancy check (system/memory.c) blocks DMA writes that
would dispatch into the device's own MMIO handlers.

CVE: CVE-2026-17588
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3926
Reported-by: XlabAI Team of Tencent Xuanwu Lab <xlabai@tencent.com>,
    Guannan Wang <wgnbuaa@gmail.com>, Zhanpeng Liu <pkugenuine@gmail.com>,
    Jiashuo Liang <761232680@qq.com>, Guancheng Li <lgcpku@gmail.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4195
Reported By: Ken Hsu and Royce Lu of Palo Alto Networks
Message-ID: <20260915112213.525283-1-thuth@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit f91b0544fe1f9fbabf582ccaaecc08877b7e19e1)
---
 hw/usb/hcd-xhci.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 292c378bfc9..1d7c0363e95 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -458,9 +458,15 @@ static void xhci_mfwrap_timer(void *opaque)
 {
     XHCIState *xhci = opaque;
     XHCIEvent wrap = { ER_MFINDEX_WRAP, CC_SUCCESS };
+    MemReentrancyGuard *guard = &xhci->parent.mem_reentrancy_guard;
+
+    assert(!guard->engaged_in_io);
+    guard->engaged_in_io = true;
 
     xhci_event(xhci, &wrap, 0);
     xhci_mfwrap_update(xhci);
+
+    guard->engaged_in_io = false;
 }
 
 static void xhci_die(XHCIState *xhci)
@@ -1080,7 +1086,14 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
 static void xhci_ep_kick_timer(void *opaque)
 {
     XHCIEPContext *epctx = opaque;
+    MemReentrancyGuard *guard = &epctx->xhci->parent.mem_reentrancy_guard;
+
+    assert(!guard->engaged_in_io);
+    guard->engaged_in_io = true;
+
     xhci_kick_epctx(epctx, 0);
+
+    guard->engaged_in_io = false;
 }
 
 static XHCIEPContext *xhci_alloc_epctx(XHCIState *xhci,
-- 
2.53.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH hci-8.1 2/3] hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666
  2026-10-26 11:46 [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Denis V. Lunev
  2026-10-26 11:46 ` [PATCH hci-8.1 1/3] hw/usb/hcd-xhci: Set reentrancy guard in timer functions (CVE-2026-17588) #VSTOR-151666 Denis V. Lunev
@ 2026-10-26 11:46 ` Denis V. Lunev
  2026-10-26 11:50   ` no-reply
  2026-10-26 11:46 ` [PATCH hci-8.1 3/3] hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code #VSTOR-151666 Denis V. Lunev
  2026-10-26 16:13 ` [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Andrey Drobyshev
  3 siblings, 1 reply; 8+ messages in thread
From: Denis V. Lunev @ 2026-10-26 11:46 UTC (permalink / raw)
  To: andrey.drobyshev; +Cc: svt-core, den

From: Thomas Huth <thuth@redhat.com>

XHCI is a complex controller, involving lots of descriptors that
are written and read via DMA transfers. As some recent bugs like
https://gitlab.com/qemu-project/qemu/-/work_items/3926 revealed,
this can sometimes be exploited from the guest side to crash or
stall QEMU.

The code currently does DMA writes with the MEMTXATTRS_UNSPECIFIED
attribute, i.e. the controller is allowed to write to other MMIO
regions, too. However, in normal operation, this should not be
necessary, all descriptors should reside in normal memory. So let's
decrease the attack surface a little bit and limit the DMA writes
to normal memory here.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Message-ID: <20260915123242.549150-1-thuth@redhat.com>
(cherry picked from commit 89e653b77369ad2d3e579139b1fa2567daa86a79)
---
 hw/usb/hcd-xhci.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 1d7c0363e95..80d2687fb19 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -520,6 +520,7 @@ static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr,
     int i;
     uint32_t tmp[5];
     uint32_t n = len / sizeof(uint32_t);
+    const MemTxAttrs memtx_attrs = { .memory = true };
 
     assert((len % sizeof(uint32_t)) == 0);
     assert(n <= ARRAY_SIZE(tmp));
@@ -527,8 +528,7 @@ static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr,
     for (i = 0; i < n; i++) {
         tmp[i] = cpu_to_le32(buf[i]);
     }
-    if (dma_memory_write(xhci->as, addr, tmp, len,
-                         MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) {
+    if (dma_memory_write(xhci->as, addr, tmp, len, memtx_attrs) != MEMTX_OK) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n",
                       __func__);
         xhci_die(xhci);
@@ -615,6 +615,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
     XHCIInterrupter *intr = &xhci->intr[v];
     XHCITRB ev_trb;
     dma_addr_t addr;
+    const MemTxAttrs memtx_attrs = { .memory = true };
 
     ev_trb.parameter = cpu_to_le64(event->ptr);
     ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
@@ -631,7 +632,7 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
 
     addr = intr->er_start + TRB_SIZE*intr->er_ep_idx;
     if (dma_memory_write(xhci->as, addr, &ev_trb, TRB_SIZE,
-                         MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) {
+                         memtx_attrs) != MEMTX_OK) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n",
                       __func__);
         xhci_die(xhci);
@@ -2445,6 +2446,7 @@ static void xhci_detach_slot(XHCIState *xhci, USBPort *uport)
 static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
 {
     dma_addr_t ctx;
+    const MemTxAttrs memtx_attrs = { .memory = true };
 
     DPRINTF("xhci_get_port_bandwidth()\n");
 
@@ -2453,9 +2455,9 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
     DPRINTF("xhci: bandwidth context at "DMA_ADDR_FMT"\n", ctx);
 
     /* TODO: actually implement real values here. This is 80% for all ports. */
-    if (stb_dma(xhci->as, ctx, 0, MEMTXATTRS_UNSPECIFIED) != MEMTX_OK ||
+    if (stb_dma(xhci->as, ctx, 0, memtx_attrs) != MEMTX_OK ||
         dma_memory_set(xhci->as, ctx + 1, 80, xhci->numports,
-                       MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) {
+                       memtx_attrs) != MEMTX_OK) {
         qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory write failed!\n",
                       __func__);
         return CC_TRB_ERROR;
-- 
2.53.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH hci-8.1 3/3] hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code #VSTOR-151666
  2026-10-26 11:46 [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Denis V. Lunev
  2026-10-26 11:46 ` [PATCH hci-8.1 1/3] hw/usb/hcd-xhci: Set reentrancy guard in timer functions (CVE-2026-17588) #VSTOR-151666 Denis V. Lunev
  2026-10-26 11:46 ` [PATCH hci-8.1 2/3] hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666 Denis V. Lunev
@ 2026-10-26 11:46 ` Denis V. Lunev
  2026-10-26 11:53   ` no-reply
  2026-10-26 16:13 ` [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Andrey Drobyshev
  3 siblings, 1 reply; 8+ messages in thread
From: Denis V. Lunev @ 2026-10-26 11:46 UTC (permalink / raw)
  To: andrey.drobyshev; +Cc: svt-core, den

From: Thomas Huth <thuth@redhat.com>

The XHCI controller's USB port and bus callbacks -- xhci_complete(),
xhci_wakeup_endpoint(), xhci_attach(), xhci_detach(), and
xhci_wakeup() -- can be invoked from outside any MMIO handler context.
The device's mem_reentrancy_guard is therefore not engaged during
this processing.

A malicious guest can exploit this gap via MSI-X self-targeting: it
programs the MSI-X vector's message address to point at the XHCI
doorbell register array (both reside in the same BAR0 MemoryRegion).
When any of these callbacks posts an event via xhci_event() ->
xhci_intr_raise(), the resulting msix_notify() -> pci_msi_trigger()
issues an address_space_stl_le() that writes doorbell 0, triggering
xhci_process_commands() reentrantly. A CR_DISABLE_SLOT command
planted on the command ring then frees XHCITransfer/XHCIEPContext
objects that the outer call stack still references, causing a
heap use-after-free.

Fix this by setting engaged_in_io on the device's mem_reentrancy_guard
around the processing in all five callbacks. The guard is set
conditionally (only when not already engaged) because these callbacks
may also be reached from within a guarded MMIO context.

xhci_child_detach() is intentionally left unguarded: it only calls
xhci_detach_slot() which passes report=0 to xhci_ep_nuke_xfers(),
suppressing event generation, so it never reaches xhci_event().

Note: This is similar to the fixes done for CVE-2026-17588, see
f91b0544fe ("Set reentrancy guard in timer functions").

CVE: CVE-2026-111819
Message-ID: <20261020114031.687929-1-thuth@redhat.com>
Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4625
Reported-by: Ken Hsu, Royce Lu, and Bo Qu of Palo Alto Networks
Buglink: https://gitlab.com/qemu-project/qemu/-/work_items/4642
Reported-by: Nikhil Agrawal <nikhil.agrawal@mettlelabs.ai>
Signed-off-by: Thomas Huth <thuth@redhat.com>
(cherry picked from commit cfa70f3a82f581ad758586ecf408fe7f3602850f)
---
 hw/usb/hcd-xhci.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 80d2687fb19..8017ddcebd0 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -3243,49 +3243,73 @@ static const MemoryRegionOps xhci_doorbell_ops = {
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
+static bool xhci_engage_reentrancy_guard(XHCIState *xhci)
+{
+    bool prev_engaged = xhci->parent.mem_reentrancy_guard.engaged_in_io;
+
+    xhci->parent.mem_reentrancy_guard.engaged_in_io = true;
+    return prev_engaged;
+}
+
+static void xhci_restore_reentrancy_guard(XHCIState *xhci, bool engaged)
+{
+    xhci->parent.mem_reentrancy_guard.engaged_in_io = engaged;
+}
+
 static void xhci_attach(USBPort *usbport)
 {
     XHCIState *xhci = usbport->opaque;
     XHCIPort *port = xhci_lookup_port(xhci, usbport);
+    bool prev_engaged = xhci_engage_reentrancy_guard(xhci);
 
     xhci_port_update(port, 0);
+    xhci_restore_reentrancy_guard(xhci, prev_engaged);
 }
 
 static void xhci_detach(USBPort *usbport)
 {
     XHCIState *xhci = usbport->opaque;
     XHCIPort *port = xhci_lookup_port(xhci, usbport);
+    bool prev_engaged = xhci_engage_reentrancy_guard(xhci);
 
     xhci_detach_slot(xhci, usbport);
     xhci_port_update(port, 1);
+    xhci_restore_reentrancy_guard(xhci, prev_engaged);
 }
 
 static void xhci_wakeup(USBPort *usbport)
 {
     XHCIState *xhci = usbport->opaque;
     XHCIPort *port = xhci_lookup_port(xhci, usbport);
+    bool prev_engaged;
 
     assert(port);
     if (get_field(port->portsc, PORTSC_PLS) != PLS_U3) {
         return;
     }
+    prev_engaged = xhci_engage_reentrancy_guard(xhci);
     set_field(&port->portsc, PLS_RESUME, PORTSC_PLS);
     xhci_port_notify(port, PORTSC_PLC);
+    xhci_restore_reentrancy_guard(xhci, prev_engaged);
 }
 
 static void xhci_complete(USBPort *port, USBPacket *packet)
 {
     XHCITransfer *xfer = container_of(packet, XHCITransfer, packet);
+    XHCIState *xhci = xfer->epctx->xhci;
+    bool prev_engaged;
 
     if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
         xhci_ep_nuke_one_xfer(xfer, 0);
         return;
     }
+    prev_engaged = xhci_engage_reentrancy_guard(xhci);
     xhci_try_complete_packet(xfer);
     xhci_kick_epctx(xfer->epctx, xfer->streamid);
     if (xfer->complete) {
         xhci_ep_free_xfer(xfer);
     }
+    xhci_restore_reentrancy_guard(xhci, prev_engaged);
 }
 
 static void xhci_child_detach(USBPort *uport, USBDevice *child)
@@ -3337,6 +3361,7 @@ static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep,
 {
     XHCIState *xhci = container_of(bus, XHCIState, bus);
     int slotid;
+    bool prev_engaged;
 
     DPRINTF("%s\n", __func__);
     slotid = ep->dev->addr;
@@ -3345,7 +3370,9 @@ static void xhci_wakeup_endpoint(USBBus *bus, USBEndpoint *ep,
         DPRINTF("%s: oops, no slot for dev %d\n", __func__, ep->dev->addr);
         return;
     }
+    prev_engaged = xhci_engage_reentrancy_guard(xhci);
     xhci_kick_ep(xhci, slotid, xhci_find_epid(ep), stream);
+    xhci_restore_reentrancy_guard(xhci, prev_engaged);
 }
 
 static USBBusOps xhci_bus_ops = {
-- 
2.53.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH hci-8.1 2/3] hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666
  2026-10-26 11:46 ` [PATCH hci-8.1 2/3] hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666 Denis V. Lunev
@ 2026-10-26 11:50   ` no-reply
  0 siblings, 0 replies; 8+ messages in thread
From: no-reply @ 2026-10-26 11:50 UTC (permalink / raw)
  To: Denis V. Lunev, andrey.drobyshev; +Cc: svt-core, den

> From: Thomas Huth <thuth@redhat.com>
> 
> XHCI is a complex controller, involving lots of descriptors that
> are written and read via DMA transfers. As some recent bugs like
> https://gitlab.com/qemu-project/qemu/-/work_items/3926 revealed,
> this can sometimes be exploited from the guest side to crash or
> stall QEMU.
> 
> The code currently does DMA writes with the MEMTXATTRS_UNSPECIFIED
> attribute, i.e. the controller is allowed to write to other MMIO
> regions, too. However, in normal operation, this should not be
> necessary, all descriptors should reside in normal memory. So let's
> decrease the attack surface a little bit and limit the DMA writes
> to normal memory here.
> 
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261026114645.187003-1-den@openvz.org?part=2


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH hci-8.1 1/3] hw/usb/hcd-xhci: Set reentrancy guard in timer functions (CVE-2026-17588) #VSTOR-151666
  2026-10-26 11:46 ` [PATCH hci-8.1 1/3] hw/usb/hcd-xhci: Set reentrancy guard in timer functions (CVE-2026-17588) #VSTOR-151666 Denis V. Lunev
@ 2026-10-26 11:51   ` no-reply
  0 siblings, 0 replies; 8+ messages in thread
From: no-reply @ 2026-10-26 11:51 UTC (permalink / raw)
  To: Denis V. Lunev, andrey.drobyshev; +Cc: den, svt-core

> From: Thomas Huth <thuth@redhat.com>
> 
> The xHCI controller processes USB events from timer callbacks
> (xhci_mfwrap_timer and xhci_ep_kick_timer) outside of any MMIO handler
> context. The device's mem_reentrancy_guard is therefore not engaged
> during this processing.
> 
> A malicious guest can exploit this by pointing the event ring base
> address (er_start) at the xHCI doorbell MMIO region. When
> xhci_write_event() performs a DMA write to deliver a transfer
> completion event, the write lands on doorbell register 0. If the
> written value is 0, this triggers xhci_process_commands() reentrantly.
> A CR_DISABLE_SLOT command prepared on the command ring then frees
> endpoint and transfer objects via xhci_disable_ep() / g_free() while
> the outer call stack still holds references to them, causing a
> [ ... ]
>     Jiashuo Liang <761232680@qq.com>, Guancheng Li <lgcpku@gmail.com>
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4195
> Reported By: Ken Hsu and Royce Lu of Palo Alto Networks
> Message-ID: <20260915112213.525283-1-thuth@redhat.com>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261026114645.187003-1-den@openvz.org?part=1


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH hci-8.1 3/3] hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code #VSTOR-151666
  2026-10-26 11:46 ` [PATCH hci-8.1 3/3] hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code #VSTOR-151666 Denis V. Lunev
@ 2026-10-26 11:53   ` no-reply
  0 siblings, 0 replies; 8+ messages in thread
From: no-reply @ 2026-10-26 11:53 UTC (permalink / raw)
  To: andrey.drobyshev, Denis V. Lunev; +Cc: svt-core, den

> From: Thomas Huth <thuth@redhat.com>
> 
> The XHCI controller's USB port and bus callbacks -- xhci_complete(),
> xhci_wakeup_endpoint(), xhci_attach(), xhci_detach(), and
> xhci_wakeup() -- can be invoked from outside any MMIO handler context.
> The device's mem_reentrancy_guard is therefore not engaged during
> this processing.
> 
> A malicious guest can exploit this gap via MSI-X self-targeting: it
> programs the MSI-X vector's message address to point at the XHCI
> doorbell register array (both reside in the same BAR0 MemoryRegion).
> When any of these callbacks posts an event via xhci_event() ->
> xhci_intr_raise(), the resulting msix_notify() -> pci_msi_trigger()
> issues an address_space_stl_le() that writes doorbell 0, triggering
> xhci_process_commands() reentrantly. A CR_DISABLE_SLOT command
> [ ... ]
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4625
> Reported-by: Ken Hsu, Royce Lu, and Bo Qu of Palo Alto Networks
> Buglink: https://gitlab.com/qemu-project/qemu/-/work_items/4642
> Reported-by: Nikhil Agrawal <nikhil.agrawal@mettlelabs.ai>
> Signed-off-by: Thomas Huth <thuth@redhat.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.vzint.dev/#/patchset/20261026114645.187003-1-den@openvz.org?part=3


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666
  2026-10-26 11:46 [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Denis V. Lunev
                   ` (2 preceding siblings ...)
  2026-10-26 11:46 ` [PATCH hci-8.1 3/3] hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code #VSTOR-151666 Denis V. Lunev
@ 2026-10-26 16:13 ` Andrey Drobyshev
  3 siblings, 0 replies; 8+ messages in thread
From: Andrey Drobyshev @ 2026-10-26 16:13 UTC (permalink / raw)
  To: Denis V. Lunev; +Cc: svt-core

Ack
Applied onto hci-dev

On 10/26/26 1:46 PM, Denis V. Lunev wrote:
> A guest can crash QEMU through the emulated xHCI controller by pointing
> the event ring, or an MSI-X vector, at the controller's own doorbell
> register. An event posted outside MMIO context, such as a USB transfer
> completion from the main loop, is then written by DMA into doorbell 0
> and runs the command ring re-entrantly. A Disable Slot command planted
> there frees the transfer and endpoint the caller still holds.
> 
> VSTOR-151666 is this crash on a production node: qemu-kvm SIGSEGV in
> xhci_ep_free_xfer() <- xhci_complete() <- usb_msd_command_complete().
> In the core, intr[0].er_start equals BAR0 + 0x2000, which is doorbell 0,
> and most crashes of that VM follow the
> "Blocked re-entrant IO on MemoryRegion: doorbell at addr: 0x0" warning
> by a second or two.
> 
> Upstream fixed it with these three commits from Thomas Huth:
> 
>   f91b0544fe  engage the re-entrancy guard in the xHCI timer callbacks
>               (CVE-2026-17588)
>   89e653b773  restrict xHCI DMA writes to RAM, so events cannot reach
>               MMIO at all
>   cfa70f3a82  engage the guard in xhci_complete() and the other port
>               callbacks (CVE-2026-111819); this is the path that crashed
> 
> All three cherry-pick cleanly onto hci-dev with no changes. The only
> local edit is the #VSTOR-151666 tag in the subjects.
> 
> Upstream has no test for either CVE. hw/usb/hcd-xhci.c builds, and the
> existing usb-hcd-xhci-test qtest passes. The attack itself has not been
> reproduced.
> 
> The same series is needed on hci-8.0, hci-7.4 and hci-7.3 and will be
> sent separately.
> 
> Signed-off-by: Denis V. Lunev <den@openvz.org>
> 
> Thomas Huth (3):
>   hw/usb/hcd-xhci: Set reentrancy guard in timer functions
>     (CVE-2026-17588) #VSTOR-151666
>   hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666
>   hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code
>     #VSTOR-151666
> 
>  hw/usb/hcd-xhci.c | 52 ++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 47 insertions(+), 5 deletions(-)
> 
> 
> base-commit: f3c1d9ef263edfab8d2a273078493bb766dcf8f8


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-10-26 16:13 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-26 11:46 [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Denis V. Lunev
2026-10-26 11:46 ` [PATCH hci-8.1 1/3] hw/usb/hcd-xhci: Set reentrancy guard in timer functions (CVE-2026-17588) #VSTOR-151666 Denis V. Lunev
2026-10-26 11:51   ` no-reply
2026-10-26 11:46 ` [PATCH hci-8.1 2/3] hw/usb/hcd-xhci: Limit DMA transfers to plain memory #VSTOR-151666 Denis V. Lunev
2026-10-26 11:50   ` no-reply
2026-10-26 11:46 ` [PATCH hci-8.1 3/3] hw/usb/hcd-xhci: More reentrancy guard fixes for the XHCI code #VSTOR-151666 Denis V. Lunev
2026-10-26 11:53   ` no-reply
2026-10-26 16:13 ` [PATCH hci-8.1 0/3] hw/usb/hcd-xhci: fix guest-triggerable use-after-free (CVE-2026-17588, CVE-2026-111819) #VSTOR-151666 Andrey Drobyshev

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox