lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260121131417.9582-3-ilpo.jarvinen@linux.intel.com>
Date: Wed, 21 Jan 2026 15:14:17 +0200
From: Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>
To: Ville Syrjälä <ville.syrjala@...ux.intel.com>,
	linux-pci@...r.kernel.org,
	Bjorn Helgaas <bhelgaas@...gle.com>,
	Christian König <christian.koenig@....com>,
	Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>,
	linux-kernel@...r.kernel.org
Cc: stable@...r.kernel.org
Subject: [PATCH 2/2] PCI: Fix Resizable BAR restore order

The commit 337b1b566db0 ("PCI: Fix restoring BARs on BAR resize
rollback path") changed BAR resize to layer rebar code and resource
setup/restore code cleanly. Unfortunately, it did not consider how the
value of the BAR Size field impacts the read-only bits in the Base
Address Register (PCIe7 spec, sec. 7.8.6.3). That is, it very much
matters in which order the BAR Size and Base Address Register are
restored.

Post-337b1b566db0 ("PCI: Fix restoring BARs on BAR resize rollback
path") during BAR resize rollback, pci_do_resource_release_and_resize()
attempts to restore the old address to the BAR that was resized, but it
can fail to setup the address correctly if the address has too low bits
set that collide with the bits that are still read-only. As a result,
kernel's resource and BAR will be out-of-sync.

Fix this by restoring BAR Size before rolling back the resource
changes and restoring the BAR.

Fixes: 337b1b566db0 ("PCI: Fix restoring BARs on BAR resize rollback path")
Link: https://lore.kernel.org/linux-pci/aW_w1oFQCzUxGYtu@intel.com/
Cc: stable@...r.kernel.org
Reported-by: Ville Syrjälä <ville.syrjala@...ux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>
---
 drivers/pci/rebar.c     | 18 +-----------------
 drivers/pci/setup-bus.c | 20 ++++++++++++++++++--
 2 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/drivers/pci/rebar.c b/drivers/pci/rebar.c
index ecdebdeb2dff..39f8cf3b70d5 100644
--- a/drivers/pci/rebar.c
+++ b/drivers/pci/rebar.c
@@ -295,7 +295,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
 			int exclude_bars)
 {
 	struct pci_host_bridge *host;
-	int old, ret;
 
 	/* Check if we must preserve the firmware's resource assignment */
 	host = pci_find_host_bridge(dev->bus);
@@ -308,21 +307,6 @@ int pci_resize_resource(struct pci_dev *dev, int resno, int size,
 	if (!pci_rebar_size_supported(dev, resno, size))
 		return -EINVAL;
 
-	old = pci_rebar_get_current_size(dev, resno);
-	if (old < 0)
-		return old;
-
-	ret = pci_rebar_set_size(dev, resno, size);
-	if (ret)
-		return ret;
-
-	ret = pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
-	if (ret)
-		goto error_resize;
-	return 0;
-
-error_resize:
-	pci_rebar_set_size(dev, resno, old);
-	return ret;
+	return pci_do_resource_release_and_resize(dev, resno, size, exclude_bars);
 }
 EXPORT_SYMBOL(pci_resize_resource);
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 9c374feafc77..a61d38777cdc 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -2504,12 +2504,20 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
 	struct resource *b_win, *r;
 	LIST_HEAD(saved);
 	unsigned int i;
-	int ret = 0;
+	int old, ret;
 
 	b_win = pbus_select_window(bus, res);
 	if (!b_win)
 		return -EINVAL;
 
+	old = pci_rebar_get_current_size(pdev, resno);
+	if (old < 0)
+		return old;
+
+	ret = pci_rebar_set_size(pdev, resno, size);
+	if (ret)
+		return ret;
+
 	pci_dev_for_each_resource(pdev, r, i) {
 		if (i >= PCI_BRIDGE_RESOURCES)
 			break;
@@ -2542,7 +2550,15 @@ int pci_do_resource_release_and_resize(struct pci_dev *pdev, int resno, int size
 	return ret;
 
 restore:
-	/* Revert to the old configuration */
+	/*
+	 * Revert to the old configuration.
+	 *
+	 * BAR Size must be restored first because it affects the read-only
+	 * bits in BAR (the old address might not be restorable otherwise
+	 * due to low address bits).
+	 */
+	pci_rebar_set_size(pdev, resno, old);
+
 	list_for_each_entry(dev_res, &saved, list) {
 		struct resource *res = dev_res->res;
 		struct pci_dev *dev = dev_res->dev;
-- 
2.39.5


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ