summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib-cdev.c
diff options
context:
space:
mode:
authorKent Gibson <warthog618@gmail.com>2023-12-21 09:20:36 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-01-05 15:13:31 +0100
commitc0c4e9767e57b6693f9a99b4e21f043d810f67a7 (patch)
tree6fe02c6be44e8f467786d39c42d8c8d4bba835a1 /drivers/gpio/gpiolib-cdev.c
parent8bdcedfdb026ff5141d53f435df4eeda5c6b12f7 (diff)
gpiolib: cdev: add gpio_device locking wrapper around gpio_ioctl()
[ Upstream commit 1d656bd259edb89dc1d9938ec5c5389867088546 ] While the GPIO cdev gpio_ioctl() call is in progress, the kernel can call gpiochip_remove() which will set gdev->chip to NULL, after which any subsequent access will cause a crash. gpio_ioctl() was overlooked by the previous fix to protect syscalls (bdbbae241a04), so add protection for that. Fixes: bdbbae241a04 ("gpiolib: protect the GPIO device against being dropped while in use by user-space") Fixes: d7c51b47ac11 ("gpio: userspace ABI for reading/writing GPIO lines") Fixes: 3c0d9c635ae2 ("gpiolib: cdev: support GPIO_V2_GET_LINE_IOCTL and GPIO_V2_LINE_GET_VALUES_IOCTL") Fixes: aad955842d1c ("gpiolib: cdev: support GPIO_V2_GET_LINEINFO_IOCTL and GPIO_V2_GET_LINEINFO_WATCH_IOCTL") Signed-off-by: Kent Gibson <warthog618@gmail.com> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/gpio/gpiolib-cdev.c')
-rw-r--r--drivers/gpio/gpiolib-cdev.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 2a2e0691462b..1db991cb2efc 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -2224,10 +2224,7 @@ static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *ip)
return 0;
}
-/*
- * gpio_ioctl() - ioctl handler for the GPIO chardev
- */
-static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long gpio_ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg)
{
struct gpio_chardev_data *cdev = file->private_data;
struct gpio_device *gdev = cdev->gdev;
@@ -2264,6 +2261,17 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
}
+/*
+ * gpio_ioctl() - ioctl handler for the GPIO chardev
+ */
+static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct gpio_chardev_data *cdev = file->private_data;
+
+ return call_ioctl_locked(file, cmd, arg, cdev->gdev,
+ gpio_ioctl_unlocked);
+}
+
#ifdef CONFIG_COMPAT
static long gpio_ioctl_compat(struct file *file, unsigned int cmd,
unsigned long arg)