diff mbox series

[v2,1/2] hwmon: (lm90) Prevent integer overflow of temperature calculations

Message ID 20210620211408.3893-2-digetx@gmail.com (mailing list archive)
State Superseded
Headers show
Series Support temperature trips by HWMON core and LM90 driver | expand

Commit Message

Dmitry Osipenko June 20, 2021, 9:14 p.m. UTC
The minimum temperature value that is passed to the driver is unlimited
and value that is close to INT_MIN results in integer overflow of
temperature calculations made by the driver. Limit the value in order
to prevent the overflow. For now the overflow condition is harmless,
but thermal framework won't work properly once we will support the
set_trips() callback because it will pass INT_MIN value to the driver.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/hwmon/lm90.c | 6 ++++++
 1 file changed, 6 insertions(+)

Comments

Guenter Roeck June 21, 2021, 12:12 p.m. UTC | #1
On Mon, Jun 21, 2021 at 12:14:07AM +0300, Dmitry Osipenko wrote:
> The minimum temperature value that is passed to the driver is unlimited
> and value that is close to INT_MIN results in integer overflow of
> temperature calculations made by the driver. Limit the value in order
> to prevent the overflow. For now the overflow condition is harmless,
> but thermal framework won't work properly once we will support the
> set_trips() callback because it will pass INT_MIN value to the driver.
> 

AFAICS that should only happen for lm99 because all other values
are bound in the temp_to_xxx functions. Where else do you see an
overflow (or underflow) ?

Thanks,
Guenter

> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  drivers/hwmon/lm90.c | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
> index b53f17511b05..6e2fa976098f 100644
> --- a/drivers/hwmon/lm90.c
> +++ b/drivers/hwmon/lm90.c
> @@ -1028,6 +1028,9 @@ static int lm90_set_temp11(struct lm90_data *data, int index, long val)
>  	struct reg *regp = &reg[index];
>  	int err;
>  
> +	/* prevent integer overflow */
> +	val = max(val, -128000l);
> +
>  	/* +16 degrees offset for temp2 for the LM99 */
>  	if (data->kind == lm99 && index <= 2)
>  		val -= 16000;
> @@ -1088,6 +1091,9 @@ static int lm90_set_temp8(struct lm90_data *data, int index, long val)
>  	struct i2c_client *client = data->client;
>  	int err;
>  
> +	/* prevent integer overflow */
> +	val = max(val, -128000l);
> +
>  	/* +16 degrees offset for temp2 for the LM99 */
>  	if (data->kind == lm99 && index == 3)
>  		val -= 16000;
> -- 
> 2.30.2
>
Dmitry Osipenko June 21, 2021, 12:14 p.m. UTC | #2
21.06.2021 15:12, Guenter Roeck пишет:
> On Mon, Jun 21, 2021 at 12:14:07AM +0300, Dmitry Osipenko wrote:
>> The minimum temperature value that is passed to the driver is unlimited
>> and value that is close to INT_MIN results in integer overflow of
>> temperature calculations made by the driver. Limit the value in order
>> to prevent the overflow. For now the overflow condition is harmless,
>> but thermal framework won't work properly once we will support the
>> set_trips() callback because it will pass INT_MIN value to the driver.
>>
> AFAICS that should only happen for lm99 because all other values
> are bound in the temp_to_xxx functions. Where else do you see an
> overflow (or underflow) ?

You're correct that the overflow affects only lm99. But why we should
ignore it?
Guenter Roeck June 21, 2021, 2:24 p.m. UTC | #3
On Mon, Jun 21, 2021 at 03:14:40PM +0300, Dmitry Osipenko wrote:
> 21.06.2021 15:12, Guenter Roeck пишет:
> > On Mon, Jun 21, 2021 at 12:14:07AM +0300, Dmitry Osipenko wrote:
> >> The minimum temperature value that is passed to the driver is unlimited
> >> and value that is close to INT_MIN results in integer overflow of
> >> temperature calculations made by the driver. Limit the value in order
> >> to prevent the overflow. For now the overflow condition is harmless,
> >> but thermal framework won't work properly once we will support the
> >> set_trips() callback because it will pass INT_MIN value to the driver.
> >>
> > AFAICS that should only happen for lm99 because all other values
> > are bound in the temp_to_xxx functions. Where else do you see an
> > overflow (or underflow) ?
> 
> You're correct that the overflow affects only lm99. But why we should
> ignore it?

That isn't the point. The point is that you claimed there would be a
generic underflow, which is not the case. That means we'll only need
to apply the fix to the lm99 specific code (which unconditionally
subtracts an offset from the provided value, causing the underflow).

Anyway, thanks for alerting me to the issue. As it turns out, there are
other underflow issues in the driver. With improved module test scripts,
I get:

Testing lm90 ...
temp1_crit_hyst: Suspected underflow: [min=54000, read 85000, written -9223372036854775808]
Testing lm99 ...
temp1_crit_hyst: Suspected underflow: [min=96000, read 127000, written -9223372036854775808]
temp2_crit: Suspected underflow: [min=-112000, read 143000, written -9223372036854775808]
temp2_min: Suspected underflow: [min=-112000, read 143875, written -9223372036854775808]
temp2_max: Suspected underflow: [min=-112000, read 143875, written -9223372036854775808]

So we'll need fixes for lm99 temp2_{min/max/crit} and for temp1_crit_hyst
(the latter affects all chips supported by the driver).

Thanks,
Guenter
Dmitry Osipenko June 21, 2021, 3:35 p.m. UTC | #4
21.06.2021 17:24, Guenter Roeck пишет:
> On Mon, Jun 21, 2021 at 03:14:40PM +0300, Dmitry Osipenko wrote:
>> 21.06.2021 15:12, Guenter Roeck пишет:
>>> On Mon, Jun 21, 2021 at 12:14:07AM +0300, Dmitry Osipenko wrote:
>>>> The minimum temperature value that is passed to the driver is unlimited
>>>> and value that is close to INT_MIN results in integer overflow of
>>>> temperature calculations made by the driver. Limit the value in order
>>>> to prevent the overflow. For now the overflow condition is harmless,
>>>> but thermal framework won't work properly once we will support the
>>>> set_trips() callback because it will pass INT_MIN value to the driver.
>>>>
>>> AFAICS that should only happen for lm99 because all other values
>>> are bound in the temp_to_xxx functions. Where else do you see an
>>> overflow (or underflow) ?
>>
>> You're correct that the overflow affects only lm99. But why we should
>> ignore it?
> 
> That isn't the point. The point is that you claimed there would be a
> generic underflow, which is not the case. That means we'll only need
> to apply the fix to the lm99 specific code (which unconditionally
> subtracts an offset from the provided value, causing the underflow).
> 
> Anyway, thanks for alerting me to the issue. As it turns out, there are
> other underflow issues in the driver. With improved module test scripts,
> I get:
> 
> Testing lm90 ...
> temp1_crit_hyst: Suspected underflow: [min=54000, read 85000, written -9223372036854775808]
> Testing lm99 ...
> temp1_crit_hyst: Suspected underflow: [min=96000, read 127000, written -9223372036854775808]
> temp2_crit: Suspected underflow: [min=-112000, read 143000, written -9223372036854775808]
> temp2_min: Suspected underflow: [min=-112000, read 143875, written -9223372036854775808]
> temp2_max: Suspected underflow: [min=-112000, read 143875, written -9223372036854775808]
> 
> So we'll need fixes for lm99 temp2_{min/max/crit} and for temp1_crit_hyst
> (the latter affects all chips supported by the driver).

I'll prepare v3 with the updated commit message and fixed
temp1_crit_hyst, thank you.
diff mbox series

Patch

diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index b53f17511b05..6e2fa976098f 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -1028,6 +1028,9 @@  static int lm90_set_temp11(struct lm90_data *data, int index, long val)
 	struct reg *regp = &reg[index];
 	int err;
 
+	/* prevent integer overflow */
+	val = max(val, -128000l);
+
 	/* +16 degrees offset for temp2 for the LM99 */
 	if (data->kind == lm99 && index <= 2)
 		val -= 16000;
@@ -1088,6 +1091,9 @@  static int lm90_set_temp8(struct lm90_data *data, int index, long val)
 	struct i2c_client *client = data->client;
 	int err;
 
+	/* prevent integer overflow */
+	val = max(val, -128000l);
+
 	/* +16 degrees offset for temp2 for the LM99 */
 	if (data->kind == lm99 && index == 3)
 		val -= 16000;