diff options
author | Guenter Roeck <linux@roeck-us.net> | 2016-12-04 21:20:52 -0500 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2016-12-12 14:33:44 -0500 |
commit | 59715f4d16c27985b6866ebdced76e4e9cd63c33 (patch) | |
tree | 67735f7f317298618673d75360c00079ea67593c | |
parent | ca1b10b8250247fb5f241d1cb894c102203378bb (diff) |
hwmon: (emcw201) Fix overflows seen when writing into limit attributes
Writes into temperature and voltage limit attributes can overflow
due to multiplications with unchecked parameters. Also, the input
parameter to DIV_ROUND_CLOSEST() needis to be range checked.
Reviewed-by: Jean Delvare <jdelvare@suse.de>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/hwmon/emc6w201.c | 8 |
1 files changed, 5 insertions, 3 deletions
diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index f37fe2011640..4aee5adf9ef2 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c | |||
@@ -215,12 +215,13 @@ static ssize_t set_in(struct device *dev, struct device_attribute *devattr, | |||
215 | if (err < 0) | 215 | if (err < 0) |
216 | return err; | 216 | return err; |
217 | 217 | ||
218 | val = DIV_ROUND_CLOSEST(val * 0xC0, nominal_mv[nr]); | 218 | val = clamp_val(val, 0, 255 * nominal_mv[nr] / 192); |
219 | val = DIV_ROUND_CLOSEST(val * 192, nominal_mv[nr]); | ||
219 | reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr) | 220 | reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr) |
220 | : EMC6W201_REG_IN_HIGH(nr); | 221 | : EMC6W201_REG_IN_HIGH(nr); |
221 | 222 | ||
222 | mutex_lock(&data->update_lock); | 223 | mutex_lock(&data->update_lock); |
223 | data->in[sf][nr] = clamp_val(val, 0, 255); | 224 | data->in[sf][nr] = val; |
224 | err = emc6w201_write8(client, reg, data->in[sf][nr]); | 225 | err = emc6w201_write8(client, reg, data->in[sf][nr]); |
225 | mutex_unlock(&data->update_lock); | 226 | mutex_unlock(&data->update_lock); |
226 | 227 | ||
@@ -252,12 +253,13 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, | |||
252 | if (err < 0) | 253 | if (err < 0) |
253 | return err; | 254 | return err; |
254 | 255 | ||
256 | val = clamp_val(val, -127000, 127000); | ||
255 | val = DIV_ROUND_CLOSEST(val, 1000); | 257 | val = DIV_ROUND_CLOSEST(val, 1000); |
256 | reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr) | 258 | reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr) |
257 | : EMC6W201_REG_TEMP_HIGH(nr); | 259 | : EMC6W201_REG_TEMP_HIGH(nr); |
258 | 260 | ||
259 | mutex_lock(&data->update_lock); | 261 | mutex_lock(&data->update_lock); |
260 | data->temp[sf][nr] = clamp_val(val, -127, 127); | 262 | data->temp[sf][nr] = val; |
261 | err = emc6w201_write8(client, reg, data->temp[sf][nr]); | 263 | err = emc6w201_write8(client, reg, data->temp[sf][nr]); |
262 | mutex_unlock(&data->update_lock); | 264 | mutex_unlock(&data->update_lock); |
263 | 265 | ||