Re: [PATCH v2] vfio/pci: sanitize bogus INTx interrupt pin values
From: Alex Williamson
Date: Wed Apr 01 2026 - 19:01:24 EST
On Sun, 29 Mar 2026 00:01:26 +0100
Christos Longros <chris.longros@xxxxxxxxx> wrote:
> Some PCI devices may report out-of-range interrupt pin values in
> config space (e.g., 0xFF when the device is in an error state).
> The VFIO PCI config virtualization layer passes these values through
> to userspace, causing QEMU to crash with an assertion failure in
> pci_irq_handler() when it computes irq_num = pin - 1, which exceeds
> PCI_NUM_PINS (4).
>
> The existing code already handles bogus VF interrupt pins (set to 0
> per SR-IOV spec 3.4.1.18), but physical functions with out-of-range
> pin values are not caught. Extend the condition that clears the
> virtualized interrupt pin to also cover values outside 1-4.
The description has taken quite a change in direction between v1 and
v2, which makes me wonder what's actually happening here. v1 suggested
this was an issue with a specific RTL NIC where the pin register reads
as 0xFF, but proposes a generic solution. v2 proposes the same
solution, but drops the reference to the RTL NIC, instead suggesting
that a device "in an error state" might have this trait.
If the device is in error state and the PIN register reads as 0xFF,
does all of config space read as 0xFF? Was the PIN register valid
before? How did it get into an "error state".
If this has only actually been observed with this RTL NIC, is it
really an error state or is the hardware non-spec compliant, trying to
indicate lack of INTx support with 0xFF rather than 0x0.
It would be surprising if a device in an error state was only broken
relative to the INTx PIN register, and exposing a broken device only
masking the INTx support seems incomplete. If we're dealing with a
specific broken device, maybe the right answer is a quirk to set
pdev->irq to zero.
Please elaborate on what's actually happening here. Thanks,
Alex
> Signed-off-by: Christos Longros <chris.longros@xxxxxxxxx>
> ---
> drivers/vfio/pci/vfio_pci_config.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c
> index b4e39253f..ed75c1cc3 100644
> --- a/drivers/vfio/pci/vfio_pci_config.c
> +++ b/drivers/vfio/pci/vfio_pci_config.c
> @@ -1829,8 +1829,17 @@ int vfio_config_init(struct vfio_pci_core_device *vdev)
> cpu_to_le16(PCI_COMMAND_MEMORY);
> }
>
> + /*
> + * Sanitize bogus interrupt pin values. Valid pins are 1 (INTA)
> + * through 4 (INTD); anything else disables legacy interrupts.
> + */
> + if (vconfig[PCI_INTERRUPT_PIN] > 4)
> + pci_info(pdev, "Bogus INTx pin %d, disabling INTx virtualization\n",
> + vconfig[PCI_INTERRUPT_PIN]);
> +
> if (!IS_ENABLED(CONFIG_VFIO_PCI_INTX) || vdev->nointx ||
> - !vdev->pdev->irq || vdev->pdev->irq == IRQ_NOTCONNECTED)
> + !vdev->pdev->irq || vdev->pdev->irq == IRQ_NOTCONNECTED ||
> + vconfig[PCI_INTERRUPT_PIN] > 4)
> vconfig[PCI_INTERRUPT_PIN] = 0;
>
> ret = vfio_cap_init(vdev);