hw/pci/pcie_sriov.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
Commit 3f9cfaa92c96 ("virtio-pci: Implement SR-IOV PF") added an
unconditional call from virtio_pci_exit() to pcie_sriov_pf_exit().
pcie_sriov_pf_exit() reads from the SR-IOV Capability in Configuration
Space:
uint8_t *cfg = dev->config + dev->exp.sriov_cap;
...
unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This results in undefined behavior when dev->exp.sriov_cap is 0 because
this is not an SR-IOV device. For example, unparent_vfs() segfaults when
total_vfs happens to be non-zero.
Fix this by returning early from pcie_sriov_pf_exit() when
dev->exp.sriov_cap is 0 because this is not an SR-IOV device.
Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
Cc: Michael S. Tsirkin <mst@redhat.com>
Reported-by: Qing Wang <qinwang@redhat.com>
Buglink: https://issues.redhat.com/browse/RHEL-116443
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
hw/pci/pcie_sriov.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
index 8a4bf0d6f7..cf1b5b5c05 100644
--- a/hw/pci/pcie_sriov.c
+++ b/hw/pci/pcie_sriov.c
@@ -195,7 +195,9 @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
void pcie_sriov_pf_exit(PCIDevice *dev)
{
- uint8_t *cfg = dev->config + dev->exp.sriov_cap;
+ if (dev->exp.sriov_cap == 0) {
+ return;
+ }
if (dev->exp.sriov_pf.vf_user_created) {
uint16_t ven_id = pci_get_word(dev->config + PCI_VENDOR_ID);
@@ -211,6 +213,8 @@ void pcie_sriov_pf_exit(PCIDevice *dev)
pci_config_set_device_id(dev->exp.sriov_pf.vf[i]->config, vf_dev_id);
}
} else {
+ uint8_t *cfg = dev->config + dev->exp.sriov_cap;
+
unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF));
}
}
--
2.51.0
On Wed, Sep 24, 2025 at 11:51:53AM -0400, Stefan Hajnoczi wrote:
> Commit 3f9cfaa92c96 ("virtio-pci: Implement SR-IOV PF") added an
> unconditional call from virtio_pci_exit() to pcie_sriov_pf_exit().
>
> pcie_sriov_pf_exit() reads from the SR-IOV Capability in Configuration
> Space:
>
> uint8_t *cfg = dev->config + dev->exp.sriov_cap;
> ...
> unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF));
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> This results in undefined behavior when dev->exp.sriov_cap is 0 because
> this is not an SR-IOV device. For example, unparent_vfs() segfaults when
> total_vfs happens to be non-zero.
>
> Fix this by returning early from pcie_sriov_pf_exit() when
> dev->exp.sriov_cap is 0 because this is not an SR-IOV device.
>
> Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Reported-by: Qing Wang <qinwang@redhat.com>
> Buglink: https://issues.redhat.com/browse/RHEL-116443
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
> hw/pci/pcie_sriov.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
CCing qemu-stable
>
> diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c
> index 8a4bf0d6f7..cf1b5b5c05 100644
> --- a/hw/pci/pcie_sriov.c
> +++ b/hw/pci/pcie_sriov.c
> @@ -195,7 +195,9 @@ bool pcie_sriov_pf_init(PCIDevice *dev, uint16_t offset,
>
> void pcie_sriov_pf_exit(PCIDevice *dev)
> {
> - uint8_t *cfg = dev->config + dev->exp.sriov_cap;
> + if (dev->exp.sriov_cap == 0) {
> + return;
> + }
>
> if (dev->exp.sriov_pf.vf_user_created) {
> uint16_t ven_id = pci_get_word(dev->config + PCI_VENDOR_ID);
> @@ -211,6 +213,8 @@ void pcie_sriov_pf_exit(PCIDevice *dev)
> pci_config_set_device_id(dev->exp.sriov_pf.vf[i]->config, vf_dev_id);
> }
> } else {
> + uint8_t *cfg = dev->config + dev->exp.sriov_cap;
> +
> unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF));
> }
> }
> --
> 2.51.0
>
On 24.09.2025 20:51, Stefan Hajnoczi wrote:
> On Wed, Sep 24, 2025 at 11:51:53AM -0400, Stefan Hajnoczi wrote:
>> Commit 3f9cfaa92c96 ("virtio-pci: Implement SR-IOV PF") added an
>> unconditional call from virtio_pci_exit() to pcie_sriov_pf_exit().
>>
>> pcie_sriov_pf_exit() reads from the SR-IOV Capability in Configuration
>> Space:
>>
>> uint8_t *cfg = dev->config + dev->exp.sriov_cap;
>> ...
>> unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF));
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>
>> This results in undefined behavior when dev->exp.sriov_cap is 0 because
>> this is not an SR-IOV device. For example, unparent_vfs() segfaults when
>> total_vfs happens to be non-zero.
>>
>> Fix this by returning early from pcie_sriov_pf_exit() when
>> dev->exp.sriov_cap is 0 because this is not an SR-IOV device.
>>
>> Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>> Cc: Michael S. Tsirkin <mst@redhat.com>
>> Reported-by: Qing Wang <qinwang@redhat.com>
>> Buglink: https://issues.redhat.com/browse/RHEL-116443
>> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>> ---
>> hw/pci/pcie_sriov.c | 6 +++++-
>> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> CCing qemu-stable
Ping? Can we apply this to the master branch, so I can pick it
up for the stable series?
Thanks,
/mjt
On 2025/09/27 22:58, Michael Tokarev wrote:
> On 24.09.2025 20:51, Stefan Hajnoczi wrote:
>> On Wed, Sep 24, 2025 at 11:51:53AM -0400, Stefan Hajnoczi wrote:
>>> Commit 3f9cfaa92c96 ("virtio-pci: Implement SR-IOV PF") added an
>>> unconditional call from virtio_pci_exit() to pcie_sriov_pf_exit().
>>>
>>> pcie_sriov_pf_exit() reads from the SR-IOV Capability in Configuration
>>> Space:
>>>
>>> uint8_t *cfg = dev->config + dev->exp.sriov_cap;
>>> ...
>>> unparent_vfs(dev, pci_get_word(cfg + PCI_SRIOV_TOTAL_VF));
>>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>>
>>> This results in undefined behavior when dev->exp.sriov_cap is 0 because
>>> this is not an SR-IOV device. For example, unparent_vfs() segfaults when
>>> total_vfs happens to be non-zero.
>>>
>>> Fix this by returning early from pcie_sriov_pf_exit() when
>>> dev->exp.sriov_cap is 0 because this is not an SR-IOV device.
>>>
>>> Cc: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
>>> Cc: Michael S. Tsirkin <mst@redhat.com>
>>> Reported-by: Qing Wang <qinwang@redhat.com>
>>> Buglink: https://issues.redhat.com/browse/RHEL-116443
>>> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>>> ---
>>> hw/pci/pcie_sriov.c | 6 +++++-
>>> 1 file changed, 5 insertions(+), 1 deletion(-)
>>
>> CCing qemu-stable
>
> Ping? Can we apply this to the master branch, so I can pick it
> up for the stable series?
Reviewed-by: Akihiko Odaki <odaki@rsg.ci.i.u-tokyo.ac.jp>
I also think it should have:
Fixes: cab1398a60eb ("pcie_sriov: Reuse SR-IOV VF device instances")
Regards,
Akihiko Odaki
© 2016 - 2026 Red Hat, Inc.