* [PATCH 1/3] PCI: Fix NULL dereference when shrinking window without optional size
2026-11-09 14:45 [PATCH 0/3] PCI: Fix hotplug memory distribute Ilpo Järvinen
@ 2026-11-09 14:45 ` Ilpo Järvinen
2026-11-09 14:45 ` [PATCH 2/3] PCI: Fix start of available space for the next bridge during distribution Ilpo Järvinen
2026-11-09 14:45 ` [PATCH 3/3] PCI: Honor window granularity during resource distribution Ilpo Järvinen
2 siblings, 0 replies; 4+ messages in thread
From: Ilpo Järvinen @ 2026-11-09 14:45 UTC (permalink / raw)
To: Bjorn Helgaas, Mika Westerberg, linux-pci, Ilpo Järvinen,
linux-kernel
Cc: Sashiko, stable
adjust_bridge_window() assumes a bridge window it needs to shrink is on
add_list. A window is only added to add_list when it has optional size
or alignment. When resource distribution gives a window that is not on
add_list less space than its required size, res_to_dev_res() returns NULL
that is unconditionally dereferenced.
Consider a hotplug Root Port with no spare pref space and a switch below
it with two non-hotplug Downstream Ports. 02:00.0 has a 2M pref BAR below
it and 02:01.0 a 1M one. Alignment leaves only 1M of pref space for
02:00.0, and hot-add (emulated using a remove+rescan cycle) crashes in
the inlined adjust_bridge_window():
BUG: kernel NULL pointer dereference, address: 0000000000000030
RIP: 0010:pci_bus_distribute_available_resources+0x19b/0x4b0
Call Trace:
<TASK>
pci_bus_distribute_available_resources+0x468/0x4b0
pci_bus_distribute_available_resources+0x468/0x4b0
pci_bridge_distribute_available_resources+0x7a/0x90
pci_assign_unassigned_bridge_resources+0x43/0xe0
pci_rescan_bus_bridge_resize+0x23/0x40
bus_rescan_store+0x63/0x80
The required size must not be shrunk, so return early when the window
has no optional size.
Fixes: dc4b4d04e1ca ("PCI: Prevent shrinking bridge window from its required size")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Cc: stable@vger.kernel.org
---
As it was a non-public run of sashiko, no link is available to sashiko's
report.
drivers/pci/setup-bus.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index ed16ef7c26fa..bd0974def921 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1896,7 +1896,11 @@ static void adjust_bridge_window(struct pci_dev *bridge, struct resource *res,
break;
}
+ /* Without optional size, there is nothing to shrink. */
dev_res = res_to_dev_res(add_list, res);
+ if (!dev_res)
+ return;
+
add_size = size - new_size;
if (add_size < dev_res->add_size) {
dev_res->add_size -= add_size;
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 2/3] PCI: Fix start of available space for the next bridge during distribution
2026-11-09 14:45 [PATCH 0/3] PCI: Fix hotplug memory distribute Ilpo Järvinen
2026-11-09 14:45 ` [PATCH 1/3] PCI: Fix NULL dereference when shrinking window without optional size Ilpo Järvinen
@ 2026-11-09 14:45 ` Ilpo Järvinen
2026-11-09 14:45 ` [PATCH 3/3] PCI: Honor window granularity during resource distribution Ilpo Järvinen
2 siblings, 0 replies; 4+ messages in thread
From: Ilpo Järvinen @ 2026-11-09 14:45 UTC (permalink / raw)
To: Bjorn Helgaas, Mika Westerberg, linux-pci, linux-kernel
Cc: Ilpo Järvinen, Claude:claude-opus-5-5, stable
After distributing space to a bridge,
pci_bus_distribute_available_resources() advances available[i].start with
"+= end + 1". As .start and .end are addresses, not a base and a size,
this adds start a second time. The space left for the following bridges
then starts at a bogus address, which skews their alignment calculations.
Set start to just past the space given to the previous bridge.
Fixes: 08f0a15ee8ad ("PCI: Align extra resources for hotplug bridges properly")
Reported-by: Claude:claude-opus-5-5 <noreply@anthropic.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Cc: stable@vger.kernel.org
---
drivers/pci/setup-bus.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index bd0974def921..9d8b22d1e6ad 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2077,7 +2077,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
pci_bus_distribute_available_resources(b, add_list, available);
for (i = 0; i < PCI_P2P_BRIDGE_RESOURCE_NUM; i++)
- available[i].start += available[i].end + 1;
+ available[i].start = available[i].end + 1;
}
}
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread* [PATCH 3/3] PCI: Honor window granularity during resource distribution
2026-11-09 14:45 [PATCH 0/3] PCI: Fix hotplug memory distribute Ilpo Järvinen
2026-11-09 14:45 ` [PATCH 1/3] PCI: Fix NULL dereference when shrinking window without optional size Ilpo Järvinen
2026-11-09 14:45 ` [PATCH 2/3] PCI: Fix start of available space for the next bridge during distribution Ilpo Järvinen
@ 2026-11-09 14:45 ` Ilpo Järvinen
2 siblings, 0 replies; 4+ messages in thread
From: Ilpo Järvinen @ 2026-11-09 14:45 UTC (permalink / raw)
To: Bjorn Helgaas, Mika Westerberg, linux-pci, linux-kernel
Cc: Ilpo Järvinen, Sashiko, stable
When a bus below a hotplug bridge has BARs smaller than the window
granularity, removing them leaves available[i].start unaligned.
pci_bus_distribute_available_resources() then aligns the start up for the
downstream bridge but keeps the end, so the size passed to
adjust_bridge_window() has a sub-granularity tail. The bridge window ends
up not being a multiple of the window granularity.
Align the size down to the window granularity after aligning the start.
Consider a hotplug Root Port (bus 01) with a Switch Upstream Port (bus 02)
below it that has an e1000 and an ivshmem with a 64k pref BAR as its other
Functions. When the switch is hot-added (emulated with a remove and
rescan), /proc/iomem before and after this change is:
faa00000-fe9fffff : PCI Bus 0000:01
- faa00000-fe8200ff : PCI Bus 0000:02
+ faa00000-fe7fffff : PCI Bus 0000:02
faa00000-fc8fffff : PCI Bus 0000:03
faa00000-faa000ff : 0000:03:00.0
fc900000-fe6fffff : PCI Bus 0000:04
- fe820100-fe8201ff : 0000:01:00.2
- fe840000-fe85ffff : 0000:01:00.1
+ fe800000-fe81ffff : 0000:01:00.1
+ fe820000-fe8200ff : 0000:01:00.2
...
100000000-13fffffff : PCI Bus 0000:01
- 100000000-12000ffff : PCI Bus 0000:02
+ 100000000-11fffffff : PCI Bus 0000:02
100000000-10fffffff : PCI Bus 0000:03
100000000-10fffffff : 0000:03:00.0
110000000-117ffffff : PCI Bus 0000:04
- 120010000-12001ffff : 0000:01:00.2
+ 120000000-12000ffff : 0000:01:00.2
Before, the bus 02 windows end at fe8200ff and 12000ffff, which are not 1M
aligned and thus impossible for a bridge window. As such an end cannot be
written to the bridge, the resource tree does not match what the bridge
actually uses: it decodes up to fe8fffff and 1200fffff, covering the BARs
of 01:00.1 and 01:00.2.
Fixes: 9db0b9b6a142 ("PCI: Take other bus devices into account when distributing resources")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Cc: stable@vger.kernel.org
---
drivers/pci/setup-bus.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 9d8b22d1e6ad..5651966f3029 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1974,7 +1974,7 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
unsigned int normal_bridges = 0, hotplug_bridges = 0;
struct pci_dev *dev, *bridge = bus->self;
resource_size_t per_bridge[PCI_P2P_BRIDGE_RESOURCE_NUM];
- resource_size_t align;
+ resource_size_t align, win_align;
int i;
for (i = 0; i < PCI_P2P_BRIDGE_RESOURCE_NUM; i++) {
@@ -1989,10 +1989,22 @@ static void pci_bus_distribute_available_resources(struct pci_bus *bus,
* window.
*/
align = pci_resource_alignment(bridge, res);
- if (!resource_assigned(res) && align)
+ if (!resource_assigned(res) && align) {
available[i].start = min(ALIGN(available[i].start, align),
available[i].end + 1);
+ /*
+ * Small BARs on the parent bus may result in a
+ * size that is not a multiple of the window
+ * granularity (usually 1M), which is impossible
+ * for a bridge window.
+ */
+ win_align = pci_min_window_alignment(bus, res->flags);
+ resource_set_size(&available[i],
+ ALIGN_DOWN(resource_size(&available[i]),
+ win_align));
+ }
+
/*
* Now that we have adjusted for alignment, update the
* bridge window resources to fill as much remaining
--
2.47.3
^ permalink raw reply [flat|nested] 4+ messages in thread