[PATCH 06/17] hwmon: (adm1026) Fix overflows seen when writing into limit attributes
Fix overflows seen when writing large values into voltage limit, temperature limit, temperature offset, and DAC attributes. Overflows are seen due to unbound multiplications and additions. Signed-off-by: Guenter Roeck--- drivers/hwmon/adm1026.c | 26 +- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index e67b9a50ac7c..b2a5d9e5c590 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -197,8 +197,9 @@ static int adm1026_scaling[] = { /* .001 Volts */ }; #define NEG12_OFFSET 16000 #define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from)) -#define INS_TO_REG(n, val) (clamp_val(SCALE(val, adm1026_scaling[n], 192),\ - 0, 255)) +#define INS_TO_REG(n, val) \ + SCALE(clamp_val(val, 0, 255 * adm1026_scaling[n] / 192), \ + adm1026_scaling[n], 192) #define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n])) /* @@ -215,11 +216,11 @@ static int adm1026_scaling[] = { /* .001 Volts */ #define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0) /* Temperature is reported in 1 degC increments */ -#define TEMP_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \ - / 1000, -127, 127)) +#define TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \ + 1000) #define TEMP_FROM_REG(val) ((val) * 1000) -#define OFFSET_TO_REG(val) (clamp_val(((val) + ((val) < 0 ? -500 : 500)) \ - / 1000, -127, 127)) +#define OFFSET_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), \ +1000) #define OFFSET_FROM_REG(val) ((val) * 1000) #define PWM_TO_REG(val) (clamp_val(val, 0, 255)) @@ -233,7 +234,8 @@ static int adm1026_scaling[] = { /* .001 Volts */ * indicates that the DAC could be used to drive the fans, but in our * example board (Arima HDAMA) it isn't connected to the fans at all. */ -#define DAC_TO_REG(val) (clamp_val(val) * 255) + 500) / 2500), 0, 255)) +#define DAC_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, 0, 2500) * 255, \ + 2500) #define DAC_FROM_REG(val) (((val) * 2500) / 255) /* @@ -593,7 +595,10 @@ static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, return err; mutex_lock(>update_lock); - data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); + data->in_min[16] = INS_TO_REG(16, + clamp_val(val, INT_MIN, + INT_MAX - NEG12_OFFSET) + + NEG12_OFFSET); adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); mutex_unlock(>update_lock); return count; @@ -618,7 +623,10 @@ static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, return err; mutex_lock(>update_lock); - data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); + data->in_max[16] = INS_TO_REG(16, + clamp_val(val, INT_MIN, + INT_MAX - NEG12_OFFSET) + + NEG12_OFFSET); adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); mutex_unlock(>update_lock); return count; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/17] hwmon: (lm93) Fix overflows seen when writing into limit attributes
Module test shows a large number of overflows, caused by missing clamps as well as various conversions between variable types. Also fix temperature calculations for hysteresis and offset registers. For those, temperature calculations were a mix of millisecond and second based, causing reported and accepted hysteresis and offset temperatures to be widely off target. This also changes the offset and base temperature attributes to be officially reported and set in milli-degrees C. This was already the case for the base temperature attribute, even though it was documented to be reported and set in degrees C. Signed-off-by: Guenter Roeck--- Documentation/hwmon/lm93 | 26 - drivers/hwmon/lm93.c | 49 +--- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/Documentation/hwmon/lm93 b/Documentation/hwmon/lm93 index f3b2ad2ceb01..7bda7f0291e4 100644 --- a/Documentation/hwmon/lm93 +++ b/Documentation/hwmon/lm93 @@ -174,25 +174,25 @@ a "0" disables it. The h/w default is 0x0f (all temperatures bound). The function y = f(x) takes a source temperature x to a PWM output y. This function of the LM93 is derived from a base temperature and a table of 12 -temperature offsets. The base temperature is expressed in degrees C in the -sysfs files temp_auto_base. The offsets are expressed in cumulative -degrees C, with the value of offset for temperature value being +temperature offsets. The base temperature is expressed in milli-degrees C in +the sysfs files temp_auto_base. The offsets are expressed in cumulative +milli-degrees C, with the value of offset for temperature value being contained in the file temp_auto_offset. E.g. if the base temperature is 40C: offset # temp_auto_offset range pwm 1 0 -25.00% 2 0 -28.57% -3 1 40C - 41C32.14% -4 1 41C - 42C35.71% -5 2 42C - 44C39.29% -6 2 44C - 46C42.86% -7 2 48C - 50C46.43% -8 2 50C - 52C50.00% -9 2 52C - 54C53.57% - 10 2 54C - 56C57.14% - 11 2 56C - 58C71.43% - 12 2 58C - 60C85.71% +3 500 40C - 41C32.14% +4 500 41C - 42C35.71% +5 100042C - 44C39.29% +6 100044C - 46C42.86% +7 100048C - 50C46.43% +8 100050C - 52C50.00% +9 100052C - 54C53.57% + 10 100054C - 56C57.14% + 11 100056C - 58C71.43% + 12 100058C - 60C85.71% > 60C 100.00% Valid offsets are in the range 0C <= x <= 7.5C in 0.5C increments. diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 90bb04858117..7b3152368e3b 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -368,7 +368,7 @@ static unsigned LM93_IN_FROM_REG(int nr, u8 reg) * IN: mV, limits determined by channel nr * REG: scaling determined by channel nr */ -static u8 LM93_IN_TO_REG(int nr, unsigned val) +static u8 LM93_IN_TO_REG(int nr, unsigned long val) { /* range limit */ const long mv = clamp_val(val, @@ -407,9 +407,13 @@ static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid) * upper also determines which nibble of the register is returned * (the other nibble will be 0x0) */ -static u8 LM93_IN_REL_TO_REG(unsigned val, int upper, int vid) +static u8 LM93_IN_REL_TO_REG(unsigned long val, int upper, int vid) { - long uv_offset = vid * 1000 - val * 1; + long uv_offset; + + val = clamp_val(val, 0, 100); + uv_offset = vid * 1000 - val * 1; + if (upper) { uv_offset = clamp_val(uv_offset, 12500, 20); return (u8)((uv_offset / 12500 - 1) << 4); @@ -453,28 +457,23 @@ static int LM93_TEMP_OFFSET_MODE_FROM_REG(u8 sfc2, int nr) * This function is common to all 4-bit temperature offsets * reg is 4 bits right justified * mode 0 => 1C/bit, mode !0 => 0.5C/bit + * Return value in milli-degrees C. */ static int LM93_TEMP_OFFSET_FROM_REG(u8 reg, int mode) { - return (reg & 0x0f) * (mode ? 5 : 10); + return (reg & 0x0f) * (mode ? 500 : 1000); } -#define LM93_TEMP_OFFSET_MIN (0) -#define
[PATCH 08/17] hwmon: (adt7470) Fix overflows seen when writing into limit attributes
Fix overflows seen when writing large values into various temperature limit attributes. The input value passed to DIC_ROUND_CLOSEST() needs to be clamped to avoid such overflows. Signed-off-by: Guenter Roeck--- drivers/hwmon/adt7470.c | 9 +++-- 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 6e60ca53406e..8996120b8170 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -483,8 +483,7 @@ static ssize_t set_temp_min(struct device *dev, if (kstrtol(buf, 10, )) return -EINVAL; - temp = DIV_ROUND_CLOSEST(temp, 1000); - temp = clamp_val(temp, -128, 127); + temp = DIV_ROUND_CLOSEST(clamp_val(temp, -128000, 127000), 1000); mutex_lock(>lock); data->temp_min[attr->index] = temp; @@ -517,8 +516,7 @@ static ssize_t set_temp_max(struct device *dev, if (kstrtol(buf, 10, )) return -EINVAL; - temp = DIV_ROUND_CLOSEST(temp, 1000); - temp = clamp_val(temp, -128, 127); + temp = DIV_ROUND_CLOSEST(clamp_val(temp, -128000, 127000), 1000); mutex_lock(>lock); data->temp_max[attr->index] = temp; @@ -880,8 +878,7 @@ static ssize_t set_pwm_tmin(struct device *dev, if (kstrtol(buf, 10, )) return -EINVAL; - temp = DIV_ROUND_CLOSEST(temp, 1000); - temp = clamp_val(temp, -128, 127); + temp = DIV_ROUND_CLOSEST(clamp_val(temp, -128000, 127000), 1000); mutex_lock(>lock); data->pwm_tmin[attr->index] = temp; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 16/17] hwmon: (gl518sm) Fix overflows seen when writing into limit attributes
Writes into limit attributes can overflow due to additions and multiplications with unchecked parameters. Signed-off-by: Guenter Roeck--- drivers/hwmon/gl518sm.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 0212c8317bca..0a11a550c2a2 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -86,9 +86,8 @@ enum chips { gl518sm_r00, gl518sm_r80 }; #define BOOL_FROM_REG(val) ((val) ? 0 : 1) #define BOOL_TO_REG(val) ((val) ? 0 : 1) -#define TEMP_TO_REG(val) clamp_val(val) < 0 ? \ - (val) - 500 : \ - (val) + 500) / 1000) + 119), 0, 255) +#define TEMP_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val(val, -119000, 136000), \ + 1000) + 119) #define TEMP_FROM_REG(val) (((val) - 119) * 1000) static inline u8 FAN_TO_REG(long rpm, int div) @@ -101,10 +100,11 @@ static inline u8 FAN_TO_REG(long rpm, int div) } #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (48 / ((val) * (div -#define IN_TO_REG(val) clamp_valval) + 9) / 19), 0, 255) +#define IN_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val(val, 0, 255 * 19), 19) #define IN_FROM_REG(val) ((val) * 19) -#define VDD_TO_REG(val)clamp_valval) * 4 + 47) / 95), 0, 255) +#define VDD_TO_REG(val) \ + DIV_ROUND_CLOSEST(clamp_val(val, 0, 255 * 95 / 4) * 4, 95) #define VDD_FROM_REG(val) (((val) * 95 + 2) / 4) #define DIV_FROM_REG(val) (1 << (val)) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 12/17] hwmon: (dme1737) Fix overflows seen when writing into limit attributes
Writes into voltage limit, temperature limit, and temperature zone attributes can overflow due to unchecked parameters to multiplications and additions. Cc: Juerg HaefligerSigned-off-by: Guenter Roeck --- drivers/hwmon/dme1737.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 8763c4a8280c..29d082c12c74 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -279,7 +279,8 @@ static inline int IN_FROM_REG(int reg, int nominal, int res) static inline int IN_TO_REG(long val, int nominal) { - return clamp_val((val * 192 + nominal / 2) / nominal, 0, 255); + return DIV_ROUND_CLOSEST(clamp_val(val, 0, 255 * nominal / 192) * 192, +nominal); } /* @@ -295,7 +296,7 @@ static inline int TEMP_FROM_REG(int reg, int res) static inline int TEMP_TO_REG(long val) { - return clamp_val((val < 0 ? val - 500 : val + 500) / 1000, -128, 127); + return DIV_ROUND_CLOSEST(clamp_val(val, -128000, 127000), 1000); } /* Temperature range */ @@ -1028,6 +1029,8 @@ static ssize_t set_zone(struct device *dev, struct device_attribute *attr, if (err) return err; + val = clamp_val(val, -256000, 255000); + mutex_lock(>update_lock); switch (fn) { case SYS_ZONE_AUTO_POINT1_TEMP_HYST: -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/17] hwmon: (nct7802) Fix overflows seen when writing into limit attributes
Fix overflows seen when writing voltage and temperature limit attributes. The value passed to DIV_ROUND_CLOSEST() needs to be clamped. Signed-off-by: Guenter Roeck--- drivers/hwmon/nct7802.c | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c index 3ce33d244cc0..6fe71cfe0320 100644 --- a/drivers/hwmon/nct7802.c +++ b/drivers/hwmon/nct7802.c @@ -326,8 +326,9 @@ static int nct7802_write_voltage(struct nct7802_data *data, int nr, int index, int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr]; int err; - voltage = DIV_ROUND_CLOSEST(voltage, nct7802_vmul[nr]); - voltage = clamp_val(voltage, 0, 0x3ff); + voltage = DIV_ROUND_CLOSEST(clamp_val(voltage, 0, + 0x3ff * nct7802_vmul[nr]), + nct7802_vmul[nr]); mutex_lock(>access_lock); err = regmap_write(data->regmap, @@ -402,7 +403,7 @@ static ssize_t store_temp(struct device *dev, struct device_attribute *attr, if (err < 0) return err; - val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -128, 127); + val = DIV_ROUND_CLOSEST(clamp_val(val, -127000, 127000), 1000); err = regmap_write(data->regmap, nr, val & 0xff); return err ? : count; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 13/17] hwmon: (emc2103) Fix overflows seen when temperature limit attributes
Writes into temperature limit attributes can overflow due to unbound values passed to DIV_ROUND_CLOSEST(). Cc: Steve GlendinningSigned-off-by: Guenter Roeck --- drivers/hwmon/emc2103.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c index 24e395c5907d..4b870ee9b0d3 100644 --- a/drivers/hwmon/emc2103.c +++ b/drivers/hwmon/emc2103.c @@ -251,7 +251,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *da, if (result < 0) return result; - val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -63, 127); + val = DIV_ROUND_CLOSEST(clamp_val(val, -63000, 127000), 1000); mutex_lock(>update_lock); data->temp_min[nr] = val; @@ -273,7 +273,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *da, if (result < 0) return result; - val = clamp_val(DIV_ROUND_CLOSEST(val, 1000), -63, 127); + val = DIV_ROUND_CLOSEST(clamp_val(val, -63000, 127000), 1000); mutex_lock(>update_lock); data->temp_max[nr] = val; -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 05/17] hwmon: (adm1025) Fix overflows seen when writing voltage limits
Writes into voltage limit attributes can overflow due to an unbound multiplication. Signed-off-by: Guenter Roeck--- drivers/hwmon/adm1025.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index d6c767ace916..1abb4609b412 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -93,7 +93,7 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; #define IN_FROM_REG(reg, scale)(((reg) * (scale) + 96) / 192) #define IN_TO_REG(val, scale) ((val) <= 0 ? 0 : \ -(val) * 192 >= (scale) * 255 ? 255 : \ +(val) >= (scale) * 255 / 192 ? 255 : \ ((val) * 192 + (scale) / 2) / (scale)) #define TEMP_FROM_REG(reg) ((reg) * 1000) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 11/17] hwmon: (lm85) Fix overflows seen when writing voltage limit attributes
Writes into voltage limit attributes can overflow due to an unbound multiplication. Signed-off-by: Guenter Roeck--- drivers/hwmon/lm85.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index 6ff773fcaefb..29c8136ce9c5 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -136,7 +136,8 @@ static const int lm85_scaling[] = { /* .001 Volts */ #define SCALE(val, from, to) (((val) * (to) + ((from) / 2)) / (from)) #define INS_TO_REG(n, val) \ - clamp_val(SCALE(val, lm85_scaling[n], 192), 0, 255) + SCALE(clamp_val(val, 0, 255 * lm85_scaling[n] / 192), \ + lm85_scaling[n], 192) #define INSEXT_FROM_REG(n, val, ext) \ SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n]) -- 2.5.0 -- To unsubscribe from this list: send the line "unsubscribe linux-hwmon" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html