Skip to content

Commit 218bc53

Browse files
commodojic23
authored andcommitted
iio: buffer: fix use-after-free for attached_buffers array
Thanks to Lars for finding this. The free of the 'attached_buffers' array should be done as late as possible. This change moves it to iio_buffers_put(), which looks like the best place for it, since it takes place right before the IIO device data is free'd. The free of this array will be handled by calling iio_device_free(). The iio_buffers_put() function is renamed to iio_device_detach_buffers() since the role of this function changes a bit. It looks like this issue was ocurring on the error path of iio_buffers_alloc_sysfs_and_mask() and in iio_buffers_free_sysfs_and_mask() Added a comment in the doc-header of iio_device_attach_buffer() to mention how this will be free'd in case anyone is reading the code and becoming confused about it. Fixes: ee708e6 ("iio: buffer: introduce support for attaching more IIO buffers") Reported-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Alexandru Ardelean <ardeleanalex@gmail.com> Link: https://lore.kernel.org/r/20210307185444.32924-1-ardeleanalex@gmail.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 4f2d9cc commit 218bc53

File tree

3 files changed

+8
-7
lines changed

3 files changed

+8
-7
lines changed

drivers/iio/iio_core.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev);
7777

7878
void iio_disable_all_buffers(struct iio_dev *indio_dev);
7979
void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
80-
void iio_buffers_put(struct iio_dev *indio_dev);
80+
void iio_device_detach_buffers(struct iio_dev *indio_dev);
8181

8282
#else
8383

@@ -93,7 +93,7 @@ static inline void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev) {}
9393

9494
static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
9595
static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}
96-
static inline void iio_buffers_put(struct iio_dev *indio_dev) {}
96+
static inline void iio_device_detach_buffers(struct iio_dev *indio_dev) {}
9797

9898
#endif
9999

drivers/iio/industrialio-buffer.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ void iio_buffer_init(struct iio_buffer *buffer)
242242
}
243243
EXPORT_SYMBOL(iio_buffer_init);
244244

245-
void iio_buffers_put(struct iio_dev *indio_dev)
245+
void iio_device_detach_buffers(struct iio_dev *indio_dev)
246246
{
247247
struct iio_dev_opaque *iio_dev_opaque = to_iio_dev_opaque(indio_dev);
248248
struct iio_buffer *buffer;
@@ -252,6 +252,8 @@ void iio_buffers_put(struct iio_dev *indio_dev)
252252
buffer = iio_dev_opaque->attached_buffers[i];
253253
iio_buffer_put(buffer);
254254
}
255+
256+
kfree(iio_dev_opaque->attached_buffers);
255257
}
256258

257259
static ssize_t iio_show_scan_index(struct device *dev,
@@ -1633,7 +1635,6 @@ int iio_buffers_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
16331635
buffer = iio_dev_opaque->attached_buffers[unwind_idx];
16341636
__iio_buffer_free_sysfs_and_mask(buffer);
16351637
}
1636-
kfree(iio_dev_opaque->attached_buffers);
16371638
return ret;
16381639
}
16391640

@@ -1655,8 +1656,6 @@ void iio_buffers_free_sysfs_and_mask(struct iio_dev *indio_dev)
16551656
buffer = iio_dev_opaque->attached_buffers[i];
16561657
__iio_buffer_free_sysfs_and_mask(buffer);
16571658
}
1658-
1659-
kfree(iio_dev_opaque->attached_buffers);
16601659
}
16611660

16621661
/**
@@ -1779,6 +1778,8 @@ EXPORT_SYMBOL_GPL(iio_buffer_put);
17791778
* This function attaches a buffer to a IIO device. The buffer stays attached to
17801779
* the device until the device is freed. For legacy reasons, the first attached
17811780
* buffer will also be assigned to 'indio_dev->buffer'.
1781+
* The array allocated here, will be free'd via the iio_device_detach_buffers()
1782+
* call which is handled by the iio_device_free().
17821783
*/
17831784
int iio_device_attach_buffer(struct iio_dev *indio_dev,
17841785
struct iio_buffer *buffer)

drivers/iio/industrialio-core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1586,7 +1586,7 @@ static void iio_dev_release(struct device *device)
15861586
iio_device_unregister_eventset(indio_dev);
15871587
iio_device_unregister_sysfs(indio_dev);
15881588

1589-
iio_buffers_put(indio_dev);
1589+
iio_device_detach_buffers(indio_dev);
15901590

15911591
ida_simple_remove(&iio_ida, indio_dev->id);
15921592
kfree(iio_dev_opaque);

0 commit comments

Comments
 (0)