[PATCH v2 3/5] hwmon: (pmbus/adm1266) reject short block-read responses in the GPIO accessors

From: Abdurrahman Hussain

Date: Sat May 16 2026 - 19:20:28 EST


adm1266_gpio_get() and adm1266_gpio_get_multiple() both compose the
pin-status word as

pins_status = read_buf[0] + (read_buf[1] << 8);

right after i2c_smbus_read_block_data(), guarding only against an
error return. A well-behaved device returns 2 bytes for
GPIO_STATUS/PDIO_STATUS, but the helper happily reports a 0- or
1-byte response too. If the device returns 0 bytes, both read_buf
slots are uninitialized stack memory; if it returns 1 byte, read_buf[1]
is.

The composed value then flows through set_bit() into the caller's
*bits in adm1266_gpio_get_multiple(), or into the return value of
adm1266_gpio_get(), and ends up in userspace via gpiolib (sysfs and
the char-dev ioctls). That leaks a few bits of kernel stack per
request on any device whose firmware glitch, bus error, or hostile
slave produces a short block-read response.

Add the missing length check to both call sites and surface a short
response as -EIO.

Fixes: d98dfad35c38 ("hwmon: (pmbus/adm1266) Add support for GPIOs")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Abdurrahman Hussain <abdurrahman@xxxxxxxxxx>
---
drivers/hwmon/pmbus/adm1266.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c
index 4dd67c02b412..57cb7d302cdd 100644
--- a/drivers/hwmon/pmbus/adm1266.c
+++ b/drivers/hwmon/pmbus/adm1266.c
@@ -175,6 +175,8 @@ static int adm1266_gpio_get(struct gpio_chip *chip, unsigned int offset)
ret = i2c_smbus_read_block_data(data->client, pmbus_cmd, read_buf);
if (ret < 0)
return ret;
+ if (ret < 2)
+ return -EIO;

pins_status = read_buf[0] + (read_buf[1] << 8);
if (offset < ADM1266_GPIO_NR)
@@ -195,6 +197,8 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
ret = i2c_smbus_read_block_data(data->client, ADM1266_GPIO_STATUS, read_buf);
if (ret < 0)
return ret;
+ if (ret < 2)
+ return -EIO;

status = read_buf[0] + (read_buf[1] << 8);

@@ -207,6 +211,8 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
ret = i2c_smbus_read_block_data(data->client, ADM1266_PDIO_STATUS, read_buf);
if (ret < 0)
return ret;
+ if (ret < 2)
+ return -EIO;

status = read_buf[0] + (read_buf[1] << 8);


--
2.53.0