Skip to content

Commit 5467801

Browse files
Shreeya Patelbrgl
authored andcommitted
gpio: Restrict usage of GPIO chip irq members before initialization
GPIO chip irq members are exposed before they could be completely initialized and this leads to race conditions. One such issue was observed for the gc->irq.domain variable which was accessed through the I2C interface in gpiochip_to_irq() before it could be initialized by gpiochip_add_irqchip(). This resulted in Kernel NULL pointer dereference. Following are the logs for reference :- kernel: Call Trace: kernel: gpiod_to_irq+0x53/0x70 kernel: acpi_dev_gpio_irq_get_by+0x113/0x1f0 kernel: i2c_acpi_get_irq+0xc0/0xd0 kernel: i2c_device_probe+0x28a/0x2a0 kernel: really_probe+0xf2/0x460 kernel: RIP: 0010:gpiochip_to_irq+0x47/0xc0 To avoid such scenarios, restrict usage of GPIO chip irq members before they are completely initialized. Signed-off-by: Shreeya Patel <shreeya.patel@collabora.com> Cc: stable@vger.kernel.org Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
1 parent 3123109 commit 5467801

File tree

2 files changed

+28
-0
lines changed

2 files changed

+28
-0
lines changed

drivers/gpio/gpiolib.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,16 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset)
14041404
{
14051405
struct irq_domain *domain = gc->irq.domain;
14061406

1407+
#ifdef CONFIG_GPIOLIB_IRQCHIP
1408+
/*
1409+
* Avoid race condition with other code, which tries to lookup
1410+
* an IRQ before the irqchip has been properly registered,
1411+
* i.e. while gpiochip is still being brought up.
1412+
*/
1413+
if (!gc->irq.initialized)
1414+
return -EPROBE_DEFER;
1415+
#endif
1416+
14071417
if (!gpiochip_irqchip_irq_valid(gc, offset))
14081418
return -ENXIO;
14091419

@@ -1593,6 +1603,15 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
15931603

15941604
acpi_gpiochip_request_interrupts(gc);
15951605

1606+
/*
1607+
* Using barrier() here to prevent compiler from reordering
1608+
* gc->irq.initialized before initialization of above
1609+
* GPIO chip irq members.
1610+
*/
1611+
barrier();
1612+
1613+
gc->irq.initialized = true;
1614+
15961615
return 0;
15971616
}
15981617

include/linux/gpio/driver.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,15 @@ struct gpio_irq_chip {
221221
*/
222222
bool per_parent_data;
223223

224+
/**
225+
* @initialized:
226+
*
227+
* Flag to track GPIO chip irq member's initialization.
228+
* This flag will make sure GPIO chip irq members are not used
229+
* before they are initialized.
230+
*/
231+
bool initialized;
232+
224233
/**
225234
* @init_hw: optional routine to initialize hardware before
226235
* an IRQ chip will be added. This is quite useful when

0 commit comments

Comments
 (0)