[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221220000457.1163446-5-jcormier@criticallink.com>
Date: Mon, 19 Dec 2022 19:04:57 -0500
From: "Cormier, Jonathan" <jcormier@...ticallink.com>
To: linux-hwmon@...r.kernel.org
Cc: John Pruitt <jpruitt@...ticallink.com>,
Jean Delvare <jdelvare@...e.com>,
Guenter Roeck <linux@...ck-us.net>,
linux-kernel@...r.kernel.org, devicetree@...r.kernel.org,
Rob Herring <robh+dt@...nel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>,
Bob Duke <bduke@...ticallink.com>,
"Cormier, Jonathan" <jcormier@...ticallink.com>
Subject: [PATCH v2 4/4] hwmon: ltc2945: Fix possible overflows
From: John Pruitt <jpruitt@...ticallink.com>
Use 64-bit values for intermediate calculations. Check for
overflows and return INT_MAX if overflows happened.
Signed-off-by: John Pruitt <jpruitt@...ticallink.com>
Signed-off-by: "Cormier, Jonathan" <jcormier@...ticallink.com>
---
drivers/hwmon/ltc2945.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c
index fc7d399b2c85..7239422fc6db 100644
--- a/drivers/hwmon/ltc2945.c
+++ b/drivers/hwmon/ltc2945.c
@@ -126,6 +126,10 @@ static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
}
val *= 1000;
val = DIV_ROUND_CLOSEST_ULL(val, shunt_resistor);
+ /* check for overflow, use MAX value if it happened */
+ if (val > INT_MAX)
+ val = INT_MAX;
+
break;
case LTC2945_VIN_H:
case LTC2945_MAX_VIN_H:
@@ -159,12 +163,14 @@ static long long ltc2945_reg_to_val(struct device *dev, u8 reg)
}
static int ltc2945_val_to_reg(struct device *dev, u8 reg,
- unsigned long val)
+ unsigned long val_32)
{
struct ltc2945_data *data = dev_get_drvdata(dev);
struct regmap *regmap = data->regmap;
u32 shunt_resistor = data->shunt_resistor;
unsigned int control;
+ /* use 64-bit val for intermediate calculations */
+ unsigned long long val = val_32;
int ret;
switch (reg) {
@@ -184,7 +190,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
if (control & CONTROL_MULT_SELECT) {
/* 25 mV * 25 uV = 0.625 uV resolution. */
val *= shunt_resistor;
- val = DIV_ROUND_CLOSEST(val, 625 * 1000);
+ val = DIV_ROUND_CLOSEST_ULL(val, 625LL * 1000LL);
} else {
/*
* 0.5 mV * 25 uV = 0.0125 uV resolution.
@@ -192,7 +198,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
* accept loss of accuracy.
*/
val *= shunt_resistor;
- val = DIV_ROUND_CLOSEST(val, 25 * 1000) * 2;
+ val = DIV_ROUND_CLOSEST_ULL(val, 25LL * 1000LL) * 2;
}
break;
case LTC2945_VIN_H:
@@ -201,7 +207,7 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
case LTC2945_MAX_VIN_THRES_H:
case LTC2945_MIN_VIN_THRES_H:
/* 25 mV resolution. */
- val /= 25;
+ val = DIV_ROUND_CLOSEST_ULL(val, 25LL);
break;
case LTC2945_ADIN_H:
case LTC2945_MAX_ADIN_H:
@@ -218,11 +224,15 @@ static int ltc2945_val_to_reg(struct device *dev, u8 reg,
case LTC2945_MIN_SENSE_THRES_H:
/* 25 uV resolution. Convert to mA. */
val *= shunt_resistor;
- val = DIV_ROUND_CLOSEST(val, 25 * 1000);
+ val = DIV_ROUND_CLOSEST_ULL(val, 25LL * 1000LL);
break;
default:
return -EINVAL;
}
+ /* If val is too large, just return the max value */
+ if (val > INT_MAX)
+ return INT_MAX;
+
return val;
}
--
2.25.1
Powered by blists - more mailing lists