| From 39e91f3be4cba51c1560bcda3a343ed1f64dc916 Mon Sep 17 00:00:00 2001 |
| From: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| Date: Wed, 22 Jul 2020 16:51:00 +0100 |
| Subject: iio:adc:ti-adc0832 Fix alignment issue with timestamp |
| |
| From: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| |
| commit 39e91f3be4cba51c1560bcda3a343ed1f64dc916 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 an array of smaller elements on the stack. |
| |
| We fix this 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. |
| Note that previously no data could leak 'including' previous readings |
| but I don't think it is an issue to potentially leak them like |
| this now does. |
| |
| In this case the postioning of the timestamp is depends on what |
| other channels are enabled. As such we cannot use a structure to |
| make the alignment explicit as it would be missleading by suggesting |
| only one possible location for the timestamp. |
| |
| Fixes: 815bbc87462a ("iio: ti-adc0832: add triggered buffer support") |
| Reported-by: Lars-Peter Clausen <lars@metafoo.de> |
| Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com> |
| Cc: Akinobu Mita <akinobu.mita@gmail.com> |
| Cc: <Stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/20200722155103.979802-25-jic23@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/iio/adc/ti-adc0832.c | 11 ++++++++--- |
| 1 file changed, 8 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/iio/adc/ti-adc0832.c |
| +++ b/drivers/iio/adc/ti-adc0832.c |
| @@ -29,6 +29,12 @@ struct adc0832 { |
| struct regulator *reg; |
| struct mutex lock; |
| u8 mux_bits; |
| + /* |
| + * Max size needed: 16x 1 byte ADC data + 8 bytes timestamp |
| + * May be shorter if not all channels are enabled subject |
| + * to the timestamp remaining 8 byte aligned. |
| + */ |
| + u8 data[24] __aligned(8); |
| |
| u8 tx_buf[2] ____cacheline_aligned; |
| u8 rx_buf[2]; |
| @@ -200,7 +206,6 @@ static irqreturn_t adc0832_trigger_handl |
| struct iio_poll_func *pf = p; |
| struct iio_dev *indio_dev = pf->indio_dev; |
| struct adc0832 *adc = iio_priv(indio_dev); |
| - u8 data[24] = { }; /* 16x 1 byte ADC data + 8 bytes timestamp */ |
| int scan_index; |
| int i = 0; |
| |
| @@ -218,10 +223,10 @@ static irqreturn_t adc0832_trigger_handl |
| goto out; |
| } |
| |
| - data[i] = ret; |
| + adc->data[i] = ret; |
| i++; |
| } |
| - iio_push_to_buffers_with_timestamp(indio_dev, data, |
| + iio_push_to_buffers_with_timestamp(indio_dev, adc->data, |
| iio_get_time_ns(indio_dev)); |
| out: |
| mutex_unlock(&adc->lock); |