summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2021-07-25 21:08:30 +0300
committerLinus Walleij <linus.walleij@linaro.org>2021-08-10 15:47:59 +0300
commit1b73e588f47397dee6e4bdfd953e0306c60b5fe5 (patch)
treedb955633b15ef5dce93a8cb17aabd6949bbc1247
parenta022135a19a1b2f8ee1f9e90d5d9de419543904c (diff)
downloadlinux-1b73e588f47397dee6e4bdfd953e0306c60b5fe5.tar.xz
pinctrl: stmfx: Fix hazardous u8[] to unsigned long cast
Casting a small array of u8 to an unsigned long is *never* OK: - it does funny thing when the array size is less than that of a long, as it accesses random places in the stack - it makes everything even more fun with a BE kernel Fix this by building the unsigned long used as a bitmap byte by byte, in a way that works across endianess and has no undefined behaviours. An extra BUILD_BUG_ON() catches the unlikely case where the array would be larger than a single unsigned long. Fixes: 1490d9f841b1 ("pinctrl: Add STMFX GPIO expander Pinctrl/GPIO driver") Signed-off-by: Marc Zyngier <maz@kernel.org> Cc: stable@vger.kernel.org Cc: Amelie Delaunay <amelie.delaunay@foss.st.com> Cc: Linus Walleij <linus.walleij@linaro.org> Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com> Cc: Alexandre Torgue <alexandre.torgue@foss.st.com> Link: https://lore.kernel.org/r/20210725180830.250218-1-maz@kernel.org Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index 008c83107a3c..5fa2488fae87 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -566,7 +566,7 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
u8 pending[NR_GPIO_REGS];
u8 src[NR_GPIO_REGS] = {0, 0, 0};
unsigned long n, status;
- int ret;
+ int i, ret;
ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING,
&pending, NR_GPIO_REGS);
@@ -576,7 +576,9 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
src, NR_GPIO_REGS);
- status = *(unsigned long *)pending;
+ BUILD_BUG_ON(NR_GPIO_REGS > sizeof(status));
+ for (i = 0, status = 0; i < NR_GPIO_REGS; i++)
+ status |= (unsigned long)pending[i] << (i * 8);
for_each_set_bit(n, &status, gc->ngpio) {
handle_nested_irq(irq_find_mapping(gc->irq.domain, n));
stmfx_pinctrl_irq_toggle_trigger(pctl, n);