summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lechner <dlechner@baylibre.com>2025-02-18 17:17:45 -0600
committerJonathan Cameron <Jonathan.Cameron@huawei.com>2025-03-04 13:17:50 +0000
commitcafeb8a99746e218035ad000d28deeca2bad9f9c (patch)
treea30bcde5fea48d3ecce5fe640e545a9b5d05b885
parentd477cda71a3a502113b81e9d1f07948624a2f8a5 (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.c26
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);