Commit 1d656bd2 authored by Kent Gibson's avatar Kent Gibson Committed by Bartosz Golaszewski
Browse files

gpiolib: cdev: add gpio_device locking wrapper around gpio_ioctl()



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
(bdbbae24), so add protection for that.

Fixes: bdbbae24 ("gpiolib: protect the GPIO device against being dropped while in use by user-space")
Fixes: d7c51b47 ("gpio: userspace ABI for reading/writing GPIO lines")
Fixes: 3c0d9c63 ("gpiolib: cdev: support GPIO_V2_GET_LINE_IOCTL and GPIO_V2_LINE_GET_VALUES_IOCTL")
Fixes: aad95584 ("gpiolib: cdev: support GPIO_V2_GET_LINEINFO_IOCTL and GPIO_V2_GET_LINEINFO_WATCH_IOCTL")
Signed-off-by: default avatarKent Gibson <warthog618@gmail.com>
Signed-off-by: default avatarBartosz Golaszewski <bartosz.golaszewski@linaro.org>
parent ceb6a6f0
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -2481,10 +2481,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;
@@ -2521,6 +2518,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)