]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
hwmon: (pmbus/adm1266) cap PDIO scan in get_multiple at ADM1266_PDIO_NR
authorAbdurrahman Hussain <abdurrahman@nexthop.ai>
Tue, 19 May 2026 00:52:25 +0000 (17:52 -0700)
committerGuenter Roeck <linux@roeck-us.net>
Thu, 21 May 2026 13:59:05 +0000 (06:59 -0700)
adm1266_gpio_get_multiple() iterates the PDIO portion of the
caller-supplied mask using

for_each_set_bit_from(gpio_nr, mask,
      ADM1266_GPIO_NR + ADM1266_PDIO_STATUS) {
...
}

where ADM1266_PDIO_STATUS is the PMBus command code (0xE9, i.e. 233),
not the number of PDIO pins.  The intended upper bound is
ADM1266_GPIO_NR + ADM1266_PDIO_NR = 25.

gpiolib hands in a mask sized for gc.ngpio (= 25 bits on this chip),
so the iteration walks find_next_bit() up to 242, reading up to 217
extra bits (a handful of unsigned-long words: four on 64-bit, seven
on 32-bit) of whatever lives past the end of the mask in the
caller's stack.  Any incidental set bit in that range then drives a
set_bit(gpio_nr, bits) call that writes past the end of the
caller-supplied bits array too -- both out-of-bounds.

Substitute ADM1266_PDIO_NR for the constant so the scan stops at the
last real PDIO bit.

Fixes: d98dfad35c38 ("hwmon: (pmbus/adm1266) Add support for GPIOs")
Cc: stable@vger.kernel.org
Signed-off-by: Abdurrahman Hussain <abdurrahman@nexthop.ai>
Reviewed-by: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Link: https://lore.kernel.org/r/20260518-adm1266-gpio-fixes-v3-1-e425e4f88139@nexthop.ai
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
drivers/hwmon/pmbus/adm1266.c

index 1fcd86ee96fe09b4f6388abfb5a7ef4c46783e0a..4b2a8a765a4ec17fd3114db272a2c84e817c633a 100644 (file)
@@ -212,7 +212,7 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
        status = read_buf[0] + (read_buf[1] << 8);
 
        *bits = 0;
-       for_each_set_bit_from(gpio_nr, mask, ADM1266_GPIO_NR + ADM1266_PDIO_STATUS) {
+       for_each_set_bit_from(gpio_nr, mask, ADM1266_GPIO_NR + ADM1266_PDIO_NR) {
                if (test_bit(gpio_nr - ADM1266_GPIO_NR, &status))
                        set_bit(gpio_nr, bits);
        }