diff options
| author | Johan Hovold <johan@kernel.org> | 2015-01-12 11:12:25 -0500 |
|---|---|---|
| committer | Linus Walleij <linus.walleij@linaro.org> | 2015-01-14 08:24:29 -0500 |
| commit | 225fce83cb72e1bffb712a33ce47c210c770f8ab (patch) | |
| tree | ff753de5fbb156b1990dc83782a195d8ec5cc081 | |
| parent | 5539b3c938d64a60cb1fc442ac3ce9263d52de0c (diff) | |
gpio: fix gpio-chip list corruption
Fix potential corruption of gpio-chip list due to failure to remove the
chip from the list before returning in gpiochip_add error path.
The chip could be long gone when the global list is next traversed,
something which could lead to a null-pointer dereference. In the best
case (chip not deallocated) we are just leaking the gpio range.
Fixes: 14e85c0e69d5 ("gpio: remove gpio_descs global array")
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
| -rw-r--r-- | drivers/gpio/gpiolib.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 89c59f5f1924..ac5944b4e4d8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
| @@ -248,7 +248,8 @@ int gpiochip_add(struct gpio_chip *chip) | |||
| 248 | base = gpiochip_find_base(chip->ngpio); | 248 | base = gpiochip_find_base(chip->ngpio); |
| 249 | if (base < 0) { | 249 | if (base < 0) { |
| 250 | status = base; | 250 | status = base; |
| 251 | goto unlock; | 251 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 252 | goto err_free_descs; | ||
| 252 | } | 253 | } |
| 253 | chip->base = base; | 254 | chip->base = base; |
| 254 | } | 255 | } |
| @@ -288,11 +289,8 @@ int gpiochip_add(struct gpio_chip *chip) | |||
| 288 | acpi_gpiochip_add(chip); | 289 | acpi_gpiochip_add(chip); |
| 289 | 290 | ||
| 290 | status = gpiochip_export(chip); | 291 | status = gpiochip_export(chip); |
| 291 | if (status) { | 292 | if (status) |
| 292 | acpi_gpiochip_remove(chip); | 293 | goto err_remove_chip; |
| 293 | of_gpiochip_remove(chip); | ||
| 294 | goto fail; | ||
| 295 | } | ||
| 296 | 294 | ||
| 297 | pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, | 295 | pr_debug("%s: registered GPIOs %d to %d on device: %s\n", __func__, |
| 298 | chip->base, chip->base + chip->ngpio - 1, | 296 | chip->base, chip->base + chip->ngpio - 1, |
| @@ -300,9 +298,14 @@ int gpiochip_add(struct gpio_chip *chip) | |||
| 300 | 298 | ||
| 301 | return 0; | 299 | return 0; |
| 302 | 300 | ||
| 303 | unlock: | 301 | err_remove_chip: |
| 302 | acpi_gpiochip_remove(chip); | ||
| 303 | of_gpiochip_remove(chip); | ||
| 304 | spin_lock_irqsave(&gpio_lock, flags); | ||
| 305 | list_del(&chip->list); | ||
| 304 | spin_unlock_irqrestore(&gpio_lock, flags); | 306 | spin_unlock_irqrestore(&gpio_lock, flags); |
| 305 | fail: | 307 | fail: |
| 308 | err_free_descs: | ||
| 306 | kfree(descs); | 309 | kfree(descs); |
| 307 | chip->desc = NULL; | 310 | chip->desc = NULL; |
| 308 | 311 | ||
