If a passthrough device's config space is unreadable at realize time (wedged link, surprise removal, powered-off GPU, etc.), the read of PCI_INTERRUPT_PIN comes back as 0xff. That value is non-zero, so it passes the "!pin" early-return check, and vfio_intx_enable() turns it into an out-of-range intx.pin (254). That value survives into pci_irq_deassert() -> pci_set_irq() -> pci_irq_handler(), which asserts 0 <= irq_num < PCI_NUM_PINS and aborts, killing the whole qemu-kvm process with SIGABRT instead of just failing the device.
Reject pin values outside the legal PCI_INTERRUPT_PIN range so this now surfaces as an ordinary device realize failure. Signed-off-by: Denis V. Lunev <[email protected]> CC: Alex Williamson <[email protected]> CC: "Cedric Le Goater" <[email protected]> --- hw/vfio/pci.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c index c204706e63..612ee4a0db 100644 --- a/hw/vfio/pci.c +++ b/hw/vfio/pci.c @@ -812,6 +812,12 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev) PCIDevice *pdev = PCI_DEVICE(vdev); int ret; + /* pin reads back as 0xff if the device is unresponsive */ + if (pin > PCI_NUM_PINS) { + error_setg(errp, "Invalid PCI interrupt pin %d", pin); + return -EINVAL; + } + vfio_disable_interrupts(vdev); vdev->msi_vectors = g_new0(VFIOMSIVector, vdev->msix->entries); -- 2.53.0
