aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <johan@kernel.org>2015-01-12 11:12:25 -0500
committerLinus Walleij <linus.walleij@linaro.org>2015-01-14 08:24:29 -0500
commit225fce83cb72e1bffb712a33ce47c210c770f8ab (patch)
treeff753de5fbb156b1990dc83782a195d8ec5cc081
parent5539b3c938d64a60cb1fc442ac3ce9263d52de0c (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.c17
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
303unlock: 301err_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);
305fail: 307fail:
308err_free_descs:
306 kfree(descs); 309 kfree(descs);
307 chip->desc = NULL; 310 chip->desc = NULL;
308 311