[PATCH 2/2] PCI: setup-res: Guard against bus->self == NULL in _pci_assign_resource()

From: Yuguo Li

Date: Wed Jun 10 2026 - 10:05:37 EST


_pci_assign_resource() walks up the parent buses looking for a
transparent bridge to retry resource allocation against. The
termination check dereferences bus->self->transparent without first
testing bus->self.

For SR-IOV virtual buses created by virtfn_add_bus() via
pci_add_new_bus(parent, NULL, busnr) -- which happens when a VF lands
on a bus number different from its PF -- bus->self is NULL. When
__pci_assign_resource() is invoked on such a VF (e.g. via
pci_assign_resource() from userspace-triggered LTP coverage) and the
allocation fails on the first iteration, the !bus->parent test passes
because the virtual bus does have a parent, and the next term then
NULL-derefs bus->self.

Add an explicit !bus->self check, mirroring the established pattern
elsewhere in drivers/pci/ (e.g. pci.c, probe.c, pciehp_hpc.c).

Reproduced on mainline 7.1.0-rc7+ on x86_64 with an SR-IOV PF whose
VFs span multiple bus numbers, by triggering pci_assign_resource() on
a VF that lives on a virtual bus:

BUG: kernel NULL pointer dereference, address: 0000000000000860
RIP: 0010:_pci_assign_resource+0x63/0x130
Call Trace:
pci_assign_resource+0xe9/0x370
... (LTP tpci test-case 12 driving pci_assign_resource via sysfs)
do_syscall_64+0xab/0x500

This is the same SR-IOV-virtual-bus / self == NULL pattern fixed for
pci_read_bridge_bases() in commit ("PCI: Bail out of
pci_read_bridge_bases() for SR-IOV virtual buses").

Fixes: d09ee9687e02 ("PCI: improve resource allocation under transparent bridges")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yuguo Li <hugoolli@xxxxxxxxxxx>
---
drivers/pci/setup-res.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 991d3ed543f5..e8bd3d4ff923 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -353,7 +353,7 @@ static int _pci_assign_resource(struct pci_dev *dev, int resno,

bus = dev->bus;
while ((ret = __pci_assign_resource(bus, dev, resno, size, min_align))) {
- if (!bus->parent || !bus->self->transparent)
+ if (!bus->parent || !bus->self || !bus->self->transparent)
break;
bus = bus->parent;
}
--
2.43.7