diff options
author | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2020-05-17 18:29:57 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-07-22 09:22:24 +0200 |
commit | 89922d5f2ee2696943635e3c8fd6fce71ce0b11c (patch) | |
tree | 819f94c9db7b5397992f627c738eef204b5d2a54 | |
parent | fdd73b8ef420c4fb7ecd1e45f6e34181b79b2501 (diff) | |
download | linux-stable-89922d5f2ee2696943635e3c8fd6fce71ce0b11c.tar.gz linux-stable-89922d5f2ee2696943635e3c8fd6fce71ce0b11c.tar.bz2 linux-stable-89922d5f2ee2696943635e3c8fd6fce71ce0b11c.zip |
iio:health:afe4404 Fix timestamp alignment and prevent data leak.
[ Upstream commit f88ecccac4be348bbcc6d056bdbc622a8955c04d ]
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 40 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
explicitly requested. This data is allocated with kzalloc so no
data can leak appart from previous readings.
Fixes: 87aec56e27ef ("iio: health: Add driver for the TI AFE4404 heart monitor")
Reported-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Acked-by: Andrew F. Davis <afd@ti.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | drivers/iio/health/afe4404.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/iio/health/afe4404.c b/drivers/iio/health/afe4404.c index 964f5231a831..5e256b11ac87 100644 --- a/drivers/iio/health/afe4404.c +++ b/drivers/iio/health/afe4404.c @@ -91,6 +91,7 @@ static const struct reg_field afe4404_reg_fields[] = { * @regulator: Pointer to the regulator for the IC * @trig: IIO trigger for this device * @irq: ADC_RDY line interrupt number + * @buffer: Used to construct a scan to push to the iio buffer. */ struct afe4404_data { struct device *dev; @@ -99,6 +100,7 @@ struct afe4404_data { struct regulator *regulator; struct iio_trigger *trig; int irq; + s32 buffer[10] __aligned(8); }; enum afe4404_chan_id { @@ -337,17 +339,17 @@ static irqreturn_t afe4404_trigger_handler(int irq, void *private) struct iio_dev *indio_dev = pf->indio_dev; struct afe4404_data *afe = iio_priv(indio_dev); int ret, bit, i = 0; - s32 buffer[10]; for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { ret = regmap_read(afe->regmap, afe4404_channel_values[bit], - &buffer[i++]); + &afe->buffer[i++]); if (ret) goto err; } - iio_push_to_buffers_with_timestamp(indio_dev, buffer, pf->timestamp); + iio_push_to_buffers_with_timestamp(indio_dev, afe->buffer, + pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); |