iio: health: afe4403: Fix oob read in afe4403_read_raw
authorWei Yongjun <weiyongjun1@huawei.com>
Mon, 7 Nov 2022 15:19:46 +0000 (15:19 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Dec 2022 10:28:38 +0000 (11:28 +0100)
[ Upstream commit 58143c1ed5882c138a3cd2251a336fc8755f23d9 ]

KASAN report out-of-bounds read as follows:

BUG: KASAN: global-out-of-bounds in afe4403_read_raw+0x42e/0x4c0
Read of size 4 at addr ffffffffc02ac638 by task cat/279

Call Trace:
 afe4403_read_raw
 iio_read_channel_info
 dev_attr_show

The buggy address belongs to the variable:
 afe4403_channel_leds+0x18/0xffffffffffffe9e0

This issue can be reproduced by singe command:

 $ cat /sys/bus/spi/devices/spi0.0/iio\:device0/in_intensity6_raw

The array size of afe4403_channel_leds is less than channels, so access
with chan->address cause OOB read in afe4403_read_raw. Fix it by moving
access before use it.

Fixes: b36e8257641a ("iio: health/afe440x: Use regmap fields")
Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Acked-by: Andrew Davis <afd@ti.com>
Link: https://lore.kernel.org/r/20221107151946.89260-1-weiyongjun@huaweicloud.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/iio/health/afe4403.c

index d492138..b5f959b 100644 (file)
@@ -245,14 +245,14 @@ static int afe4403_read_raw(struct iio_dev *indio_dev,
                            int *val, int *val2, long mask)
 {
        struct afe4403_data *afe = iio_priv(indio_dev);
-       unsigned int reg = afe4403_channel_values[chan->address];
-       unsigned int field = afe4403_channel_leds[chan->address];
+       unsigned int reg, field;
        int ret;
 
        switch (chan->type) {
        case IIO_INTENSITY:
                switch (mask) {
                case IIO_CHAN_INFO_RAW:
+                       reg = afe4403_channel_values[chan->address];
                        ret = afe4403_read(afe, reg, val);
                        if (ret)
                                return ret;
@@ -262,6 +262,7 @@ static int afe4403_read_raw(struct iio_dev *indio_dev,
        case IIO_CURRENT:
                switch (mask) {
                case IIO_CHAN_INFO_RAW:
+                       field = afe4403_channel_leds[chan->address];
                        ret = regmap_field_read(afe->fields[field], val);
                        if (ret)
                                return ret;