| From 85e0e4bb4b0d35a19b481d623ab14b17e2ea0181 Mon Sep 17 00:00:00 2001 |
| From: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| Date: Sun, 17 May 2020 18:30:00 +0100 |
| Subject: [PATCH] iio:chemical:pms7003: Fix timestamp alignment and prevent |
| data leak. |
| |
| commit 13e945631c2ffb946c0af342812a3cd39227de6e 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. |
| 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: a1d642266c14 ("iio: chemical: add support for Plantower PMS7003 sensor") |
| Reported-by: Lars-Peter Clausen <lars@metafoo.de> |
| Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> |
| Cc: <Stable@vger.kernel.org> |
| Acked-by: Tomasz Duszynski <tomasz.duszynski@octakon.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/iio/chemical/pms7003.c b/drivers/iio/chemical/pms7003.c |
| index 23c9ab252470..07bb90d72434 100644 |
| --- a/drivers/iio/chemical/pms7003.c |
| +++ b/drivers/iio/chemical/pms7003.c |
| @@ -73,6 +73,11 @@ struct pms7003_state { |
| struct pms7003_frame frame; |
| struct completion frame_ready; |
| struct mutex lock; /* must be held whenever state gets touched */ |
| + /* Used to construct scan to push to the IIO buffer */ |
| + struct { |
| + u16 data[3]; /* PM1, PM2P5, PM10 */ |
| + s64 ts; |
| + } scan; |
| }; |
| |
| static int pms7003_do_cmd(struct pms7003_state *state, enum pms7003_cmd cmd) |
| @@ -104,7 +109,6 @@ static irqreturn_t pms7003_trigger_handler(int irq, void *p) |
| struct iio_dev *indio_dev = pf->indio_dev; |
| struct pms7003_state *state = iio_priv(indio_dev); |
| struct pms7003_frame *frame = &state->frame; |
| - u16 data[3 + 1 + 4]; /* PM1, PM2P5, PM10, padding, timestamp */ |
| int ret; |
| |
| mutex_lock(&state->lock); |
| @@ -114,12 +118,15 @@ static irqreturn_t pms7003_trigger_handler(int irq, void *p) |
| goto err; |
| } |
| |
| - data[PM1] = pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET); |
| - data[PM2P5] = pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET); |
| - data[PM10] = pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET); |
| + state->scan.data[PM1] = |
| + pms7003_get_pm(frame->data + PMS7003_PM1_OFFSET); |
| + state->scan.data[PM2P5] = |
| + pms7003_get_pm(frame->data + PMS7003_PM2P5_OFFSET); |
| + state->scan.data[PM10] = |
| + pms7003_get_pm(frame->data + PMS7003_PM10_OFFSET); |
| mutex_unlock(&state->lock); |
| |
| - iio_push_to_buffers_with_timestamp(indio_dev, data, |
| + iio_push_to_buffers_with_timestamp(indio_dev, &state->scan, |
| iio_get_time_ns(indio_dev)); |
| err: |
| iio_trigger_notify_done(indio_dev->trig); |
| -- |
| 2.27.0 |
| |