diff options
author | David Lechner <dlechner@baylibre.com> | 2025-02-18 17:17:45 -0600 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2025-03-04 13:17:50 +0000 |
commit | cafeb8a99746e218035ad000d28deeca2bad9f9c (patch) | |
tree | a30bcde5fea48d3ecce5fe640e545a9b5d05b885 | |
parent | d477cda71a3a502113b81e9d1f07948624a2f8a5 (diff) |
iio: adc: ad4695: fix out of bounds array access
Fix some out of bounds array access of st->channels_cfg in the ad4695
driver. This array only has elements for voltage channels, but it was
also being accessed for the temperature channel in a few cases causing
reading past the end of the array.
In some cases, this was harmless because the value was read but not
used. However, the in_temp_sampling_frequency attribute shares code
with the in_voltageY_sampling_frequency attributes and was trying to
read the oversampling ratio from the st->channels_cfg array. This
resulted in a garbage value being used in the calculation and the
resulting in_temp_sampling_frequency value was incorrect.
To fix, make sure we always check that we are dealing with a voltage
channel before accessing the st->channels_cfg array and use an
oversampling ratio of 1 for the temperature channel (multiplicative
identity value) since that channel doesn't support oversampling.
Fixes: 67d63185db79 ("iio: adc: ad4695: add offload-based oversampling support")
Signed-off-by: David Lechner <dlechner@baylibre.com>
Reviewed-by: Trevor Gamblin <tgamblin@baylibre.com>
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Link: https://patch.msgid.link/20250218-iio-adc-ad4695-fix-out-of-bounds-array-access-v1-1-57fef8c7a3fd@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
-rw-r--r-- | drivers/iio/adc/ad4695.c | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/drivers/iio/adc/ad4695.c b/drivers/iio/adc/ad4695.c index 9dbf326b6273..d42dea494302 100644 --- a/drivers/iio/adc/ad4695.c +++ b/drivers/iio/adc/ad4695.c @@ -1054,12 +1054,14 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, { struct ad4695_state *st = iio_priv(indio_dev); const struct iio_scan_type *scan_type; - struct ad4695_channel_config *cfg = &st->channels_cfg[chan->scan_index]; - unsigned int osr = st->channels_cfg[chan->scan_index].oversampling_ratio; + struct ad4695_channel_config *cfg; unsigned int reg_val; int ret, tmp; u8 realbits; + if (chan->type == IIO_VOLTAGE) + cfg = &st->channels_cfg[chan->scan_index]; + scan_type = iio_get_current_scan_type(indio_dev, chan); if (IS_ERR(scan_type)) return PTR_ERR(scan_type); @@ -1140,7 +1142,7 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, tmp = sign_extend32(reg_val, 15); - switch (osr) { + switch (cfg->oversampling_ratio) { case 1: *val = tmp / 4; *val2 = abs(tmp) % 4 * MICRO / 4; @@ -1180,6 +1182,10 @@ static int ad4695_read_raw(struct iio_dev *indio_dev, } case IIO_CHAN_INFO_SAMP_FREQ: { struct pwm_state state; + unsigned int osr = 1; + + if (chan->type == IIO_VOLTAGE) + osr = cfg->oversampling_ratio; ret = pwm_get_state_hw(st->cnv_pwm, &state); if (ret) @@ -1272,7 +1278,10 @@ static int __ad4695_write_raw(struct iio_dev *indio_dev, { struct ad4695_state *st = iio_priv(indio_dev); unsigned int reg_val; - unsigned int osr = st->channels_cfg[chan->scan_index].oversampling_ratio; + unsigned int osr = 1; + + if (chan->type == IIO_VOLTAGE) + osr = st->channels_cfg[chan->scan_index].oversampling_ratio; switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: @@ -1383,7 +1392,10 @@ static int ad4695_read_avail(struct iio_dev *indio_dev, }, }; struct ad4695_state *st = iio_priv(indio_dev); - unsigned int osr = st->channels_cfg[chan->scan_index].oversampling_ratio; + unsigned int osr = 1; + + if (chan->type == IIO_VOLTAGE) + osr = st->channels_cfg[chan->scan_index].oversampling_ratio; switch (mask) { case IIO_CHAN_INFO_CALIBSCALE: @@ -1738,7 +1750,7 @@ static int ad4695_probe_spi_offload(struct iio_dev *indio_dev, for (i = 0; i < indio_dev->num_channels; i++) { struct iio_chan_spec *chan = &st->iio_chan[i]; - struct ad4695_channel_config *cfg = &st->channels_cfg[i]; + struct ad4695_channel_config *cfg; /* * NB: When using offload support, all channels need to have the @@ -1759,6 +1771,8 @@ static int ad4695_probe_spi_offload(struct iio_dev *indio_dev, if (chan->type != IIO_VOLTAGE) continue; + cfg = &st->channels_cfg[i]; + chan->info_mask_separate |= BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); chan->info_mask_separate_available |= BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO); |