From: "Denis V. Lunev" <[email protected]>

qemu-kvm aborts a few seconds after starting a VM with a
passed-through GPU whose PCI_INTERRUPT_PIN comes back as an
out-of-range value: vfio_intx_enable() only guards against pin == 0
and stores vdev->intx.pin = pin - 1 with no upper-bound check. That
value later reaches pci_irq_handler()'s
assert(0 <= irq_num && irq_num < PCI_NUM_PINS) via
pci_irq_deassert() -> pci_set_irq(), aborting the process.

Legal PCI_INTERRUPT_PIN values are 0 (no legacy interrupt) or
1-PCI_NUM_PINS (INTA-INTD); reject anything else before it reaches
vdev->intx.pin, whether the out-of-range value came from a read
failure (now caught by the previous commit) or was handed back as
data by the device itself.

Signed-off-by: Denis V. Lunev <[email protected]>
CC: Alex Williamson <[email protected]>
CC: Cédric Le Goater <[email protected]>
Link: https://lore.kernel.org/qemu-devel/[email protected]
Reviewed-by: Cédric Le Goater <[email protected]>
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Signed-off-by: Cédric Le Goater <[email protected]>
(cherry picked from commit 86abb10256a58d50513d1f9c65652b7b6b7faafc)
(Mjt: context fixup for 10.0.x)
Signed-off-by: Michael Tokarev <[email protected]>

diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 168f597e782..fdf9528b05b 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -279,6 +279,11 @@ static bool vfio_intx_enable(VFIOPCIDevice *vdev, Error 
**errp)
         return true;
     }
 
+    if (pin > PCI_NUM_PINS) {
+        error_setg(errp, "invalid PCI interrupt pin %d", pin);
+        return false;
+    }
+
     vfio_disable_interrupts(vdev);
 
     vdev->intx.pin = pin - 1; /* Pin A (1) -> irq[0] */
-- 
2.47.3


Reply via email to