Skip to content

Commit a6f86f7

Browse files
committed
iio:accel:bmc150-accel: Fix timestamp alignment and prevent data leak.
One of a class of bugs pointed out by Lars in a recent review. iio_push_to_buffers_with_timestamp assumes the buffer used is aligned to the size of the timestamp (8 bytes). This is not guaranteed in this driver which uses a 16 byte array of smaller elements on the stack. As Lars also noted this anti pattern can involve a leak of data to userspace and that indeed can happen here. We close both issues by moving to a suitable structure in the iio_priv() data with alignment ensured by use of an explicit c structure. This data is allocated with kzalloc so no data can leak appart from previous readings. Fixes tag is beyond some major refactoring so likely manual backporting would be needed to get that far back. Whilst the force alignment of the ts is not strictly necessary, it does make the code less fragile. Fixes: 3bbec97 ("iio: bmc150_accel: add support for hardware fifo") Reported-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Acked-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> Cc: <Stable@vger.kernel.org>
1 parent 89226a2 commit a6f86f7

File tree

1 file changed

+12
-3
lines changed

1 file changed

+12
-3
lines changed

drivers/iio/accel/bmc150-accel-core.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,14 @@ struct bmc150_accel_data {
189189
struct mutex mutex;
190190
u8 fifo_mode, watermark;
191191
s16 buffer[8];
192+
/*
193+
* Ensure there is sufficient space and correct alignment for
194+
* the timestamp if enabled
195+
*/
196+
struct {
197+
__le16 channels[3];
198+
s64 ts __aligned(8);
199+
} scan;
192200
u8 bw_bits;
193201
u32 slope_dur;
194202
u32 slope_thres;
@@ -922,15 +930,16 @@ static int __bmc150_accel_fifo_flush(struct iio_dev *indio_dev,
922930
* now.
923931
*/
924932
for (i = 0; i < count; i++) {
925-
u16 sample[8];
926933
int j, bit;
927934

928935
j = 0;
929936
for_each_set_bit(bit, indio_dev->active_scan_mask,
930937
indio_dev->masklength)
931-
memcpy(&sample[j++], &buffer[i * 3 + bit], 2);
938+
memcpy(&data->scan.channels[j++], &buffer[i * 3 + bit],
939+
sizeof(data->scan.channels[0]));
932940

933-
iio_push_to_buffers_with_timestamp(indio_dev, sample, tstamp);
941+
iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
942+
tstamp);
934943

935944
tstamp += sample_period;
936945
}

0 commit comments

Comments
 (0)