aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimur Tabi <timur@codeaurora.org>2018-03-29 14:29:12 -0400
committerLinus Walleij <linus.walleij@linaro.org>2018-04-26 05:27:18 -0400
commitab3dbcf78f60f46d6a0ad63b1f4b690b7a427140 (patch)
tree54dc4dd788f1bed7ed77eec19ecb7cfd08daf6b8
parentf241632fd087d3d9fbd5450f4d8c8604badd8348 (diff)
gpioib: do not free unrequested descriptors
If the main loop in linehandle_create() encounters an error, it unwinds completely by freeing all previously requested GPIO descriptors. However, if the error occurs in the beginning of the loop before that GPIO is requested, then the exit code attempts to free a null descriptor. If extrachecks is enabled, gpiod_free() triggers a WARN_ON. Instead, keep a separate count of legitimate GPIOs so that only those are freed. Cc: stable@vger.kernel.org Fixes: d7c51b47ac11 ("gpio: userspace ABI for reading/writing GPIO lines") Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org> Signed-off-by: Timur Tabi <timur@codeaurora.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
-rw-r--r--drivers/gpio/gpiolib.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 43aeb07343ec..d07771797707 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -497,7 +497,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
497 struct gpiohandle_request handlereq; 497 struct gpiohandle_request handlereq;
498 struct linehandle_state *lh; 498 struct linehandle_state *lh;
499 struct file *file; 499 struct file *file;
500 int fd, i, ret; 500 int fd, i, count = 0, ret;
501 u32 lflags; 501 u32 lflags;
502 502
503 if (copy_from_user(&handlereq, ip, sizeof(handlereq))) 503 if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
@@ -558,6 +558,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
558 if (ret) 558 if (ret)
559 goto out_free_descs; 559 goto out_free_descs;
560 lh->descs[i] = desc; 560 lh->descs[i] = desc;
561 count = i;
561 562
562 if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) 563 if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
563 set_bit(FLAG_ACTIVE_LOW, &desc->flags); 564 set_bit(FLAG_ACTIVE_LOW, &desc->flags);
@@ -628,7 +629,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
628out_put_unused_fd: 629out_put_unused_fd:
629 put_unused_fd(fd); 630 put_unused_fd(fd);
630out_free_descs: 631out_free_descs:
631 for (; i >= 0; i--) 632 for (i = 0; i < count; i++)
632 gpiod_free(lh->descs[i]); 633 gpiod_free(lh->descs[i]);
633 kfree(lh->label); 634 kfree(lh->label);
634out_free_lh: 635out_free_lh: