drivers/pinctrl/intel/pinctrl-intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
intel_pinctrl_probe() declares a per-community capability_offset[]
array on the stack and only writes the slots whose CAPLIST entries
the device actually advertises:
unsigned short capability_offset[6];
...
do {
value = readl(regs + offset);
switch ((value & CAPLIST_ID_MASK) >> CAPLIST_ID_SHIFT) {
case CAPLIST_ID_GPIO_HW_INFO:
capability_offset[CAPLIST_ID_GPIO_HW_INFO] = offset;
break;
case CAPLIST_ID_PWM:
capability_offset[CAPLIST_ID_PWM] = offset;
break;
...
default:
break;
}
...
} while (offset);
...
ret = intel_pinctrl_probe_pwm(pctrl, community,
capability_offset[CAPLIST_ID_PWM]);
If a community does not advertise a PWM capability, the loop never
writes capability_offset[CAPLIST_ID_PWM] and the call to
intel_pinctrl_probe_pwm() reads an indeterminate stack value.
intel_pinctrl_probe_pwm() computes the PWM register base before it
checks PINCTRL_FEATURE_PWM:
void __iomem *base = community->regs + capability_offset + 4;
...
if (!(community->features & PINCTRL_FEATURE_PWM))
return 0;
so the base = community->regs + capability_offset + 4 expression is
evaluated using the uninitialized value on every probe for any
community that does not have CAPLIST_ID_PWM. The result is never
dereferenced when the PWM feature flag is clear, but reading an
indeterminate stack object is undefined behaviour by C, and KMSAN /
UBSAN report it at probe time.
Default the whole array to zero at declaration so unused slots are
defined (community->regs + 4) instead of indeterminate.
Fixes: 340bba73c545 ("pinctrl: intel: Improve capability support")
Signed-off-by: Stepan Ionichev <sozdayvek@gmail.com>
---
drivers/pinctrl/intel/pinctrl-intel.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 97bf5ec78..4fb4a3dab 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -1601,7 +1601,7 @@ int intel_pinctrl_probe(struct platform_device *pdev,
for (i = 0; i < pctrl->ncommunities; i++) {
struct intel_community *community = &pctrl->communities[i];
- unsigned short capability_offset[6];
+ unsigned short capability_offset[6] = { };
void __iomem *regs;
u32 revision;
u32 offset;
--
2.43.0
On Fri, May 15, 2026 at 08:00:49PM +0500, Stepan Ionichev wrote: > intel_pinctrl_probe() declares a per-community capability_offset[] > array on the stack and only writes the slots whose CAPLIST entries > the device actually advertises: Thanks, this is very long, but unfortunately bogus report. So, here basically the summary is "Check if the HW is broken". If the answer to that "yes", we have much bigger issues than some parameter being precalculated. Besides that, have you checked the code generation? Does compiler is stupid enough to calculate base before any checks? It's quite clear that the first use of base is the devm_pwm_lpss_probe(). Instead of this patch I can accept one that splits definition and assignment and be like void __iomem *base; ... base = community->regs + capability_offset + 4; chip = devm_pwm_lpss_probe(pctrl->dev, base, &info); (without any Fixes tag). -- With Best Regards, Andy Shevchenko
© 2016 - 2026 Red Hat, Inc.