From 5b51ff0887b9f88d042b92dd07fcdda4132f0ebc Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 30 Oct 2026 10:40:36 -0700 Subject: [PATCH] hwmon: (lm87) Fix drvdata type confusion in vrm_show() and vrm_store() When an LM87 or ADM1024 device is probed with VID support enabled, reading from or writing to the vrm sysfs attribute triggers a driver data type confusion in vrm_show() and vrm_store() in drivers/hwmon/lm87.c. In lm87_probe(), the driver stores the struct lm87_data pointer on the I2C client via i2c_set_clientdata() and passes the struct i2c_client pointer as the drvdata argument to devm_hwmon_device_register_with_groups(), which attaches the attribute groups to the registered hwmon device with client as its driver_data. Unlike the other sysfs callbacks that retrieve client via dev_get_drvdata() and then obtain data via i2c_get_clientdata(), vrm_show() and vrm_store() assign dev_get_drvdata(dev) directly to struct lm87_data *. Dereferencing data->vrm therefore accesses the struct i2c_client instance at offsetof(struct lm87_data, vrm), causing vrm_show() to leak an unrelated byte from struct i2c_client to userspace and vrm_store() to corrupt a byte within struct i2c_client while failing to update the actual VRM value. Fix the problem by assigning the return value from dev_get_drvdata(dev) to struct i2c_client *client and using i2c_get_clientdata() to get the actual client data. Fixes: 00a0c905ab4b ("hwmon: (lm87) Use hwmon to create the sysfs groups") Cc: stable@vger.kernel.org Signed-off-by: Guenter Roeck --- drivers/hwmon/lm87.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/lm87.c b/drivers/hwmon/lm87.c index c09074f44708..bb4e15b66355 100644 --- a/drivers/hwmon/lm87.c +++ b/drivers/hwmon/lm87.c @@ -606,13 +606,16 @@ static DEVICE_ATTR_RO(cpu0_vid); static ssize_t vrm_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct lm87_data *data = dev_get_drvdata(dev); + struct i2c_client *client = dev_get_drvdata(dev); + struct lm87_data *data = i2c_get_clientdata(client); + return sprintf(buf, "%d\n", data->vrm); } static ssize_t vrm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct lm87_data *data = dev_get_drvdata(dev); + struct i2c_client *client = dev_get_drvdata(dev); + struct lm87_data *data = i2c_get_clientdata(client); unsigned long val; int err;