gpiolib: cdev: Add INIT_KFIFO() for linereq events
authorKent Gibson <warthog618@gmail.com>
Wed, 29 May 2024 13:19:51 +0000 (21:19 +0800)
committerBartosz Golaszewski <bartosz.golaszewski@linaro.org>
Thu, 30 May 2024 09:29:10 +0000 (11:29 +0200)
The initialisation of the linereq events kfifo relies on the struct being
zeroed and a subsequent call to kfifo_alloc().  The call to kfifo_alloc()
is deferred until edge detection is first enabled for the linereq.  If the
kfifo is inadvertently accessed before the call to kfifo_alloc(), as was
the case in a recently discovered bug, it behaves as a FIFO of size 1 with
an element size of 0, so writes and reads to the kfifo appear successful
but copy no actual data.

As a defensive measure, initialise the kfifo with INIT_KFIFO() when the
events kfifo is constructed.  This initialises the kfifo element size
and zeroes its data pointer, so any inadvertant access prior to the
kfifo_alloc() call will trigger an oops.

Signed-off-by: Kent Gibson <warthog618@gmail.com>
Link: https://lore.kernel.org/r/20240529131953.195777-2-warthog618@gmail.com
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
drivers/gpio/gpiolib-cdev.c

index 9dad67ea25974ea4c2dd68d267d728af7603f2bc..d4e47960cc98b2c03c88149cc705fdb366cae233 100644 (file)
@@ -1774,6 +1774,7 @@ static int linereq_create(struct gpio_device *gdev, void __user *ip)
 
        mutex_init(&lr->config_mutex);
        init_waitqueue_head(&lr->wait);
+       INIT_KFIFO(lr->events);
        lr->event_buffer_size = ulr.event_buffer_size;
        if (lr->event_buffer_size == 0)
                lr->event_buffer_size = ulr.num_lines * 16;