iio: triggered-buffer: prevent possible freeing of wrong buffer
authorDavid Lechner <dlechner@baylibre.com>
Tue, 31 Oct 2023 21:05:19 +0000 (16:05 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Jan 2024 12:42:38 +0000 (12:42 +0000)
commit bce61476dc82f114e24e9c2e11fb064781ec563c upstream.

Commit ee708e6baacd ("iio: buffer: introduce support for attaching more
IIO buffers") introduced support for multiple buffers per indio_dev but
left indio_dev->buffer for a few legacy use cases.

In the case of the triggered buffer, iio_triggered_buffer_cleanup()
still assumes that indio_dev->buffer points to the buffer allocated by
iio_triggered_buffer_setup_ext(). However, since
iio_triggered_buffer_setup_ext() now calls iio_device_attach_buffer()
to attach the buffer, indio_dev->buffer will only point to the buffer
allocated by iio_device_attach_buffer() if it the first buffer attached.

This adds a check to make sure that no other buffer has been attached
yet to ensure that indio_dev->buffer will be assigned when
iio_device_attach_buffer() is called.

As per discussion in the review thread, we may want to deal with multiple
triggers per device, but this is a fix for the issue in the meantime and
any such support would be unlikely to be suitable for a backport.

Fixes: ee708e6baacd ("iio: buffer: introduce support for attaching more IIO buffers")
Signed-off-by: David Lechner <dlechner@baylibre.com>
Acked-by: Nuno Sa <nuno.sa@analog.com>
Link: https://lore.kernel.org/r/20231031210521.1661552-1-dlechner@baylibre.com
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/iio/buffer/industrialio-triggered-buffer.c

index c7671b1..c065159 100644 (file)
@@ -46,6 +46,16 @@ int iio_triggered_buffer_setup_ext(struct iio_dev *indio_dev,
        struct iio_buffer *buffer;
        int ret;
 
+       /*
+        * iio_triggered_buffer_cleanup() assumes that the buffer allocated here
+        * is assigned to indio_dev->buffer but this is only the case if this
+        * function is the first caller to iio_device_attach_buffer(). If
+        * indio_dev->buffer is already set then we can't proceed otherwise the
+        * cleanup function will try to free a buffer that was not allocated here.
+        */
+       if (indio_dev->buffer)
+               return -EADDRINUSE;
+
        buffer = iio_kfifo_allocate();
        if (!buffer) {
                ret = -ENOMEM;