From: Kent Gibson warthog618@gmail.com
[ Upstream commit 35d848e7a1cbba2649ed98cf58e0cdc7ee560c7a ]
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 Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/gpio/gpiolib-cdev.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index d526a4c91e82e..0b1531557f04f 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1855,6 +1855,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;