提交 b20392ad 编写于 作者: S Shreeya Patel 提交者: Zheng Zengkai

gpio: Restrict usage of GPIO chip irq members before initialization

stable inclusion
from stable-v5.10.111
commit 7e88a50704b0c49ad3f2d11e8b963341cf68a89f
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I5GL1Z

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=7e88a50704b0c49ad3f2d11e8b963341cf68a89f

--------------------------------

commit 5467801f 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: NShreeya Patel <shreeya.patel@collabora.com>
Cc: stable@vger.kernel.org
Reviewed-by: NAndy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: NLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: NBartosz Golaszewski <brgl@bgdev.pl>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
Reviewed-by: NWei Li <liwei391@huawei.com>
上级 f7125971
......@@ -1411,6 +1411,16 @@ static int gpiochip_to_irq(struct gpio_chip *gc, unsigned offset)
{
struct irq_domain *domain = gc->irq.domain;
#ifdef CONFIG_GPIOLIB_IRQCHIP
/*
* Avoid race condition with other code, which tries to lookup
* an IRQ before the irqchip has been properly registered,
* i.e. while gpiochip is still being brought up.
*/
if (!gc->irq.initialized)
return -EPROBE_DEFER;
#endif
if (!gpiochip_irqchip_irq_valid(gc, offset))
return -ENXIO;
......@@ -1604,6 +1614,15 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
acpi_gpiochip_request_interrupts(gc);
/*
* Using barrier() here to prevent compiler from reordering
* gc->irq.initialized before initialization of above
* GPIO chip irq members.
*/
barrier();
gc->irq.initialized = true;
return 0;
}
......
......@@ -224,6 +224,15 @@ struct gpio_irq_chip {
unsigned long *valid_mask,
unsigned int ngpios);
/**
* @initialized:
*
* Flag to track GPIO chip irq member's initialization.
* This flag will make sure GPIO chip irq members are not used
* before they are initialized.
*/
bool initialized;
/**
* @valid_mask:
*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册