[PATCH 2/5] PCI: of: Bound num_lanes in of_pci_get_equalization_presets()
From: shao.mingyin
Date: Fri Nov 06 2026 - 11:28:14 EST
From: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
of_pci_get_equalization_presets() copies num_lanes entries into
presets->eq_presets_8gts[] and presets->eq_presets_Ngts[i][], which are
both sized MAX_NR_LANES (16). The only in-tree caller,
dw_pcie_host_init(), passes pci->num_lanes, which comes from the
"num-lanes" DT property or from the Link Capabilities MLW field (up to 63
for PCIe r6.0), so a device advertising more than 16 lanes makes
of_property_read_*_array() write past the end of those arrays.
Return -EINVAL when num_lanes exceeds MAX_NR_LANES instead of overflowing
the output arrays. Callers below the 16-lane limit are unaffected.
Fixes: 57a4591df709 ("PCI: of: Add of_pci_get_equalization_presets() API")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Shao Mingyin <shao.mingyin@xxxxxxxxxx>
---
Tested on 7.3.0-next-20261030 (QEMU/TCG guest, KASAN) with a synthetic
device-tree node carrying 32-entry "eq-presets-*" properties, passed to
of_pci_get_equalization_presets(). No PCIe controller hardware is needed:
a TEST-ONLY hook (applied to both kernels) builds the node and calls the
function once at boot with num_lanes=32.
Calling the function with num_lanes=32 copies 32 entries into the
MAX_NR_LANES (16) eq_presets output arrays:
unpatched patched
BUG: KASAN: stack-out-of-bounds no KASAN report, ret=-EINVAL
in of_property_read_variable_u8_ (num_lanes > 16 rejected up front)
array, of_pci_get_equalization_
presets+0x181, ret=0
diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index a51dff91b196..85737043294e 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -1062,6 +1062,9 @@ int of_pci_get_equalization_presets(struct device *dev,
char name[20];
int ret;
+ if (num_lanes > MAX_NR_LANES)
+ return -EINVAL;
+
presets->eq_presets_8gts[0] = PCI_EQ_RESV;
ret = of_property_read_u16_array(dev->of_node, "eq-presets-8gts",
presets->eq_presets_8gts, num_lanes);