lkml.org 
[lkml]   [2022]   [Apr]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 294/343] gpio: Restrict usage of GPIO chip irq members before initialization
    Date
    From: Shreeya Patel <shreeya.patel@collabora.com>

    commit 5467801f1fcbdc46bc7298a84dbf3ca1ff2a7320 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 <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>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/gpio/gpiolib.c | 19 +++++++++++++++++++
    include/linux/gpio/driver.h | 9 +++++++++
    2 files changed, 28 insertions(+)

    --- a/drivers/gpio/gpiolib.c
    +++ b/drivers/gpio/gpiolib.c
    @@ -1404,6 +1404,16 @@ static int gpiochip_to_irq(struct gpio_c
    {
    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;

    @@ -1593,6 +1603,15 @@ static int gpiochip_add_irqchip(struct g

    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;
    }

    --- a/include/linux/gpio/driver.h
    +++ b/include/linux/gpio/driver.h
    @@ -219,6 +219,15 @@ struct gpio_irq_chip {
    bool per_parent_data;

    /**
    + * @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;
    +
    + /**
    * @init_hw: optional routine to initialize hardware before
    * an IRQ chip will be added. This is quite useful when
    * a particular driver wants to clear IRQ related registers

    \
     
     \ /
      Last update: 2022-04-12 10:59    [W:8.001 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site