Skip to content

Commit 0912cf0

Browse files
Shreeya Patelgregkh
authored andcommitted
gpio: Restrict usage of GPIO chip irq members before initialization
commit 5467801 upstream. 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 <[email protected]> Cc: [email protected] Reviewed-by: Andy Shevchenko <[email protected]> Reviewed-by: Linus Walleij <[email protected]> Signed-off-by: Bartosz Golaszewski <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 9ca11bd commit 0912cf0

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
@@ -1368,6 +1368,16 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned int offset)
13681368
{
13691369
struct irq_domain *domain = gc->irq.domain;
13701370

1371+
#ifdef CONFIG_GPIOLIB_IRQCHIP
1372+
/*
1373+
* Avoid race condition with other code, which tries to lookup
1374+
* an IRQ before the irqchip has been properly registered,
1375+
* i.e. while gpiochip is still being brought up.
1376+
*/
1377+
if (!gc->irq.initialized)
1378+
return -EPROBE_DEFER;
1379+
#endif
1380+
13711381
if (!gpiochip_irqchip_irq_valid(gc, offset))
13721382
return -ENXIO;
13731383

@@ -1552,6 +1562,15 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
15521562

15531563
acpi_gpiochip_request_interrupts(gc);
15541564

1565+
/*
1566+
* Using barrier() here to prevent compiler from reordering
1567+
* gc->irq.initialized before initialization of above
1568+
* GPIO chip irq members.
1569+
*/
1570+
barrier();
1571+
1572+
gc->irq.initialized = true;
1573+
15551574
return 0;
15561575
}
15571576

include/linux/gpio/driver.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,15 @@ struct gpio_irq_chip {
224224
unsigned long *valid_mask,
225225
unsigned int ngpios);
226226

227+
/**
228+
* @initialized:
229+
*
230+
* Flag to track GPIO chip irq member's initialization.
231+
* This flag will make sure GPIO chip irq members are not used
232+
* before they are initialized.
233+
*/
234+
bool initialized;
235+
227236
/**
228237
* @valid_mask:
229238
*

0 commit comments

Comments
 (0)