From 21c9077ee1e802c3727012dc6067928a35f3a611 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 22 Jul 2020 16:51:02 +0100 Subject: [PATCH] iio:adc:ina2xx Fix timestamp alignment issue. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit commit f8cd222feb82ecd82dcf610fcc15186f55f9c2b5 upstream. 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 32 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 apart from previous readings. The explicit alignment isn't technically needed here, but it reduced fragility and avoids cut and paste into drivers where it will be needed. If we want this in older stables will need manual backport due to driver reworks. Fixes: c43a102e67db ("iio: ina2xx: add support for TI INA2xx Power Monitors") Reported-by: Lars-Peter Clausen Cc: Stefan Brüns Cc: Marc Titinger Signed-off-by: Jonathan Cameron Reviewed-by: Andy Shevchenko Cc: Signed-off-by: Greg Kroah-Hartman --- drivers/iio/adc/ina2xx-adc.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c index 59b7d76e1ad2..ce7e9a2383af 100644 --- a/drivers/iio/adc/ina2xx-adc.c +++ b/drivers/iio/adc/ina2xx-adc.c @@ -117,6 +117,11 @@ struct ina2xx_chip_info { int int_time_vbus; /* Bus voltage integration time uS */ int int_time_vshunt; /* Shunt voltage integration time uS */ bool allow_async_readout; + /* data buffer needs space for channel data and timestamp */ + struct { + u16 chan[4]; + u64 ts __aligned(8); + } scan; }; static const struct ina2xx_config ina2xx_config[] = { @@ -459,7 +464,6 @@ static const struct iio_chan_spec ina2xx_channels[] = { static int ina2xx_work_buffer(struct iio_dev *indio_dev) { struct ina2xx_chip_info *chip = iio_priv(indio_dev); - unsigned short data[8]; int bit, ret, i = 0; s64 time_a, time_b; unsigned int alert; @@ -500,13 +504,12 @@ static int ina2xx_work_buffer(struct iio_dev *indio_dev) if (ret < 0) return ret; - data[i++] = val; + chip->scan.chan[i++] = val; } time_b = iio_get_time_ns(indio_dev); - iio_push_to_buffers_with_timestamp(indio_dev, - (unsigned int *)data, time_a); + iio_push_to_buffers_with_timestamp(indio_dev, &chip->scan, time_a); return (unsigned long)(time_b - time_a) / 1000; }; -- 2.20.1