[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20251124153740.2995-1-ilpo.jarvinen@linux.intel.com>
Date: Mon, 24 Nov 2025 17:37:40 +0200
From: Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>
To: Bjorn Helgaas <bhelgaas@...gle.com>,
Christian König <christian.koenig@....com>,
linux-pci@...r.kernel.org,
linux-kernel@...r.kernel.org
Cc: Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>,
Dan Carpenter <dan.carpenter@...aro.org>
Subject: [PATCH 1/1] PCI: Check pci_rebar_size_supported() input
According to Dan Carpenter, smatch detects issue with size parameter
given to pci_rebar_size_supported():
drivers/pci/rebar.c:142 pci_rebar_size_supported()
error: undefined (user controlled) shift '(((1))) << size'
The problem is this call tree:
__resource_resize_store() <- takes an unsigned long from the user
-> pci_resize_resource() <- truncates it to int
-> pci_rebar_size_supported()
The string input to __resource_resize_store() is to unsigned long and
then passed to pci_resize_resource(). There could be similar problems
also with the values coming from GPU drivers.
Add 'size' validation to pci_rebar_size_supported().
There seems to be no SZ_128T prior to this so add one to be able to
specify the largest size supported by the kernel (PCIe r7.0 spec
already defines sizes even beyond 128TB but kernel does not yet support
them).
The issue looks older than the introduction of
pci_rebar_size_supported() in the commit bb1fabd0d94e ("PCI: Add
pci_rebar_size_supported() helper").
It would be also nice to convert 'size' unsigned too everywhere, maybe
even u8 but that is left as further work.
Fixes: 8bb705e3e79d ("PCI: Add pci_resize_resource() for resizing BARs")
Reported-by: Dan Carpenter <dan.carpenter@...aro.org>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@...ux.intel.com>
---
As this is so close to the merge window, I assume this will be routed
through next but I suggest not folding it to the commit bb1fabd0d94e
("PCI: Add pci_rebar_size_supported() helper") as this should be
backported. It will fail backport immediately as pci_rebar_size_supported()
is only in pci/resource but I'll deal with it when the time comes and
create a backport for it to the older codebase.
---
drivers/pci/rebar.c | 3 +++
include/linux/sizes.h | 1 +
2 files changed, 4 insertions(+)
diff --git a/drivers/pci/rebar.c b/drivers/pci/rebar.c
index 8f7af3053cd8..a84165a196fa 100644
--- a/drivers/pci/rebar.c
+++ b/drivers/pci/rebar.c
@@ -139,6 +139,9 @@ bool pci_rebar_size_supported(struct pci_dev *pdev, int bar, int size)
{
u64 sizes = pci_rebar_get_possible_sizes(pdev, bar);
+ if (size < 0 || size > ilog2(SZ_128T) - ilog2(PCI_REBAR_MIN_SIZE))
+ return false;
+
return BIT(size) & sizes;
}
EXPORT_SYMBOL_GPL(pci_rebar_size_supported);
diff --git a/include/linux/sizes.h b/include/linux/sizes.h
index 49039494076f..f1f1a055b047 100644
--- a/include/linux/sizes.h
+++ b/include/linux/sizes.h
@@ -67,5 +67,6 @@
#define SZ_16T _AC(0x100000000000, ULL)
#define SZ_32T _AC(0x200000000000, ULL)
#define SZ_64T _AC(0x400000000000, ULL)
+#define SZ_128T _AC(0x800000000000, ULL)
#endif /* __LINUX_SIZES_H__ */
base-commit: bf0a90fc907e47344f88e5b9b241082184dbac27
--
2.39.5
Powered by blists - more mailing lists