lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ