[PATCH 07/10] pinctrl: single: Reject invalid register width in pcs_probe()

From: Lee Jones

Date: Wed Nov 11 2026 - 16:55:39 EST


If the "pinctrl-single,register-width" property specifies an unsupported
width (anything other than 8, 16, or 32), pcs_probe() hits the default
branch in the switch statement and continues without initialising
pcs->read or pcs->write, leading to a divide-by-zero in
pcs_allocate_pin_table() or a NULL function pointer dereference when
accessing registers.

Validate pcs->width immediately after reading the property and return
-EINVAL from the default branch in pcs_probe().

Fixes: 8b8b091bf07f ("pinctrl: Add one-register-per-pin type device tree based pinctrl driver")
Closes: https://sashiko.dev/#/bug/linux-a0303b6e-d0c6-4292-aeeb-fa8a21861827
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Lee Jones <lee@xxxxxxxxxx>
---
drivers/pinctrl/pinctrl-single.c | 34 ++++++++++++++++----------------
1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index e0eb7240a985..13e0ae8bb389 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1811,6 +1811,23 @@ static int pcs_probe(struct platform_device *pdev)
return ret;
}

+ switch (pcs->width) {
+ case 8:
+ pcs->read = pcs_readb;
+ pcs->write = pcs_writeb;
+ break;
+ case 16:
+ pcs->read = pcs_readw;
+ pcs->write = pcs_writew;
+ break;
+ case 32:
+ pcs->read = pcs_readl;
+ pcs->write = pcs_writel;
+ break;
+ default:
+ return -EINVAL;
+ }
+
ret = of_property_read_u32(np, "pinctrl-single,function-mask",
&pcs->fmask);
if (!ret) {
@@ -1860,23 +1877,6 @@ static int pcs_probe(struct platform_device *pdev)

platform_set_drvdata(pdev, pcs);

- switch (pcs->width) {
- case 8:
- pcs->read = pcs_readb;
- pcs->write = pcs_writeb;
- break;
- case 16:
- pcs->read = pcs_readw;
- pcs->write = pcs_writew;
- break;
- case 32:
- pcs->read = pcs_readl;
- pcs->write = pcs_writel;
- break;
- default:
- break;
- }
-
pcs->desc.name = DRIVER_NAME;
pcs->desc.pctlops = &pcs_pinctrl_ops;
pcs->desc.pmxops = &pcs_pinmux_ops;
--
2.56.0.567.gdb80ae8cd5-goog