summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimur Tabi <timur@codeaurora.org>2018-03-29 13:29:12 -0500
committerLinus Walleij <linus.walleij@linaro.org>2018-04-26 11:27:18 +0200
commitab3dbcf78f60f46d6a0ad63b1f4b690b7a427140 (patch)
tree54dc4dd788f1bed7ed77eec19ecb7cfd08daf6b8
parentf241632fd087d3d9fbd5450f4d8c8604badd8348 (diff)
downloadblackbird-op-linux-ab3dbcf78f60f46d6a0ad63b1f4b690b7a427140.tar.gz
blackbird-op-linux-ab3dbcf78f60f46d6a0ad63b1f4b690b7a427140.zip
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)
struct gpiohandle_request handlereq;
struct linehandle_state *lh;
struct file *file;
- int fd, i, ret;
+ int fd, i, count = 0, ret;
u32 lflags;
if (copy_from_user(&handlereq, ip, sizeof(handlereq)))
@@ -558,6 +558,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
if (ret)
goto out_free_descs;
lh->descs[i] = desc;
+ count = i;
if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags);
@@ -628,7 +629,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
out_put_unused_fd:
put_unused_fd(fd);
out_free_descs:
- for (; i >= 0; i--)
+ for (i = 0; i < count; i++)
gpiod_free(lh->descs[i]);
kfree(lh->label);
out_free_lh:
OpenPOWER on IntegriCloud