pinctrl: stmfx: Fix hazardous u8[] to unsigned long cast
commit 1b73e588f47397dee6e4bdfd953e0306c60b5fe5 upstream.
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: 1490d9f841
("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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d4acec5e94
commit
eda59ca42f
@ -540,7 +540,7 @@ static irqreturn_t stmfx_pinctrl_irq_thread_fn(int irq, void *dev_id)
|
|||||||
u8 pending[NR_GPIO_REGS];
|
u8 pending[NR_GPIO_REGS];
|
||||||
u8 src[NR_GPIO_REGS] = {0, 0, 0};
|
u8 src[NR_GPIO_REGS] = {0, 0, 0};
|
||||||
unsigned long n, status;
|
unsigned long n, status;
|
||||||
int ret;
|
int i, ret;
|
||||||
|
|
||||||
ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING,
|
ret = regmap_bulk_read(pctl->stmfx->map, STMFX_REG_IRQ_GPI_PENDING,
|
||||||
&pending, NR_GPIO_REGS);
|
&pending, NR_GPIO_REGS);
|
||||||
@ -550,7 +550,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,
|
regmap_bulk_write(pctl->stmfx->map, STMFX_REG_IRQ_GPI_SRC,
|
||||||
src, NR_GPIO_REGS);
|
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) {
|
for_each_set_bit(n, &status, gc->ngpio) {
|
||||||
handle_nested_irq(irq_find_mapping(gc->irq.domain, n));
|
handle_nested_irq(irq_find_mapping(gc->irq.domain, n));
|
||||||
stmfx_pinctrl_irq_toggle_trigger(pctl, n);
|
stmfx_pinctrl_irq_toggle_trigger(pctl, n);
|
||||||
|
Loading…
Reference in New Issue
Block a user