Re: [PATCH v2 1/5] gpiolib: cdev: add gpio_device locking wrapper around gpio_ioctl()

From: Bartosz Golaszewski
Date: Thu Dec 21 2023 - 04:37:50 EST


On Thu, Dec 21, 2023 at 2:21 AM Kent Gibson <warthog618@xxxxxxxxx> wrote:
>
> 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@xxxxxxxxx>
> ---
> drivers/gpio/gpiolib-cdev.c | 16 ++++++++++++----
> 1 file changed, 12 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
> index 744734405912..9155c54acc1e 100644
> --- a/drivers/gpio/gpiolib-cdev.c
> +++ b/drivers/gpio/gpiolib-cdev.c
> @@ -2598,10 +2598,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;
> @@ -2638,6 +2635,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)
> --
> 2.39.2
>

I applied this. I'll send it upstream tomorrow and once it's in
master, I'll pick up the rest on Monday.

Bart