diff options
author | Timur Tabi <timur@codeaurora.org> | 2018-03-29 13:29:12 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-05-16 10:10:26 +0200 |
commit | 0f40bb84e25e591e35741979c578ce931818308b (patch) | |
tree | c57a6763d7f1f7990ae4fa10a2e34817d695599f /drivers/gpio | |
parent | ef7c4825fe5fe9ed251bda8d4c04d47fe33c3afb (diff) | |
download | linux-exynos-0f40bb84e25e591e35741979c578ce931818308b.tar.gz linux-exynos-0f40bb84e25e591e35741979c578ce931818308b.tar.bz2 linux-exynos-0f40bb84e25e591e35741979c578ce931818308b.zip |
gpioib: do not free unrequested descriptors
commit ab3dbcf78f60f46d6a0ad63b1f4b690b7a427140 upstream.
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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpiolib.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index b4c8b25453a6..65f751adb1cd 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -443,7 +443,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; if (copy_from_user(&handlereq, ip, sizeof(handlereq))) return -EFAULT; @@ -489,6 +489,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); @@ -555,7 +556,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: |