diff mbox series

power: supply: core: Fix boundary conditions in interpolation

Message ID 4ca23609-11f4-881b-6676-83ac80dff254@dorianrudolph.com
State Accepted
Commit 093d27bb6f2d1963f927ef59c9a2d37059175426
Headers show
Series power: supply: core: Fix boundary conditions in interpolation | expand

Commit Message

Dorian Rudolph May 14, 2022, 3:23 p.m. UTC
The functions power_supply_temp2resist_simple and power_supply_ocv2cap_simple
handle boundary conditions incorrectly.
The change was introduced in a4585ba2050f460f749bbaf2b67bd56c41e30283
("power: supply: core: Use library interpolation").
There are two issues: First, the lines "high = i - 1" and "high = i" in ocv2cap
have the wrong order compared to temp2resist. As a consequence, ocv2cap
sets high=-1 if ocv>table[0].ocv, which causes an out-of-bounds read.
Second, the logic of temp2resist is also not correct.
Consider the case table[] = {{20, 100}, {10, 80}, {0, 60}}.
For temp=5, we expect a resistance of 70% by interpolation.
However, temp2resist sets high=low=2 and returns 60.

Cc: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Dorian Rudolph <mail@dorianrudolph.com>
---
 drivers/power/supply/power_supply_core.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

Comments

Linus Walleij May 14, 2022, 10:09 p.m. UTC | #1
On Sat, May 14, 2022 at 5:23 PM Dorian Rudolph <mail@dorianrudolph.com> wrote:

> The functions power_supply_temp2resist_simple and power_supply_ocv2cap_simple
> handle boundary conditions incorrectly.
> The change was introduced in a4585ba2050f460f749bbaf2b67bd56c41e30283
> ("power: supply: core: Use library interpolation").
> There are two issues: First, the lines "high = i - 1" and "high = i" in ocv2cap
> have the wrong order compared to temp2resist. As a consequence, ocv2cap
> sets high=-1 if ocv>table[0].ocv, which causes an out-of-bounds read.
> Second, the logic of temp2resist is also not correct.
> Consider the case table[] = {{20, 100}, {10, 80}, {0, 60}}.
> For temp=5, we expect a resistance of 70% by interpolation.
> However, temp2resist sets high=low=2 and returns 60.
>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Dorian Rudolph <mail@dorianrudolph.com>

My arithmetics were not with me that day. I also copypasted the error :(
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Fixes: a4585ba2050f ("power: supply: core: Use library interpolation")
Cc: stable@vger.kernel.org

Yours,
Linus Walleij
Sebastian Reichel June 9, 2022, 7:14 p.m. UTC | #2
Hi,

On Sun, May 15, 2022 at 12:09:56AM +0200, Linus Walleij wrote:
> On Sat, May 14, 2022 at 5:23 PM Dorian Rudolph <mail@dorianrudolph.com> wrote:
> 
> > The functions power_supply_temp2resist_simple and power_supply_ocv2cap_simple
> > handle boundary conditions incorrectly.
> > The change was introduced in a4585ba2050f460f749bbaf2b67bd56c41e30283
> > ("power: supply: core: Use library interpolation").
> > There are two issues: First, the lines "high = i - 1" and "high = i" in ocv2cap
> > have the wrong order compared to temp2resist. As a consequence, ocv2cap
> > sets high=-1 if ocv>table[0].ocv, which causes an out-of-bounds read.
> > Second, the logic of temp2resist is also not correct.
> > Consider the case table[] = {{20, 100}, {10, 80}, {0, 60}}.
> > For temp=5, we expect a resistance of 70% by interpolation.
> > However, temp2resist sets high=low=2 and returns 60.
> >
> > Cc: Linus Walleij <linus.walleij@linaro.org>
> > Signed-off-by: Dorian Rudolph <mail@dorianrudolph.com>
> 
> My arithmetics were not with me that day. I also copypasted the error :(
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> Fixes: a4585ba2050f ("power: supply: core: Use library interpolation")
> Cc: stable@vger.kernel.org

Thanks, queued to power-supply's fixes branch.

-- Sebastian
diff mbox series

Patch

diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index ec838c9bcc0a..3828ba9d0eab 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -801,17 +801,17 @@  int power_supply_temp2resist_simple(struct power_supply_resistance_temp_table *t
 {
 	int i, high, low;
 
-	/* Break loop at table_len - 1 because that is the highest index */
-	for (i = 0; i < table_len - 1; i++)
+	for (i = 0; i < table_len; i++)
 		if (temp > table[i].temp)
 			break;
 
 	/* The library function will deal with high == low */
-	if ((i == 0) || (i == (table_len - 1)))
-		high = i;
+	if (i == 0)
+		high = low = i;
+	else if (i == table_len)
+		high = low = i - 1;
 	else
-		high = i - 1;
-	low = i;
+		high = (low = i) - 1;
 
 	return fixp_linear_interpolate(table[low].temp,
 				       table[low].resistance,
@@ -838,17 +838,17 @@  int power_supply_ocv2cap_simple(struct power_supply_battery_ocv_table *table,
 {
 	int i, high, low;
 
-	/* Break loop at table_len - 1 because that is the highest index */
-	for (i = 0; i < table_len - 1; i++)
+	for (i = 0; i < table_len; i++)
 		if (ocv > table[i].ocv)
 			break;
 
 	/* The library function will deal with high == low */
-	if ((i == 0) || (i == (table_len - 1)))
-		high = i - 1;
+	if (i == 0)
+		high = low = i;
+	else if (i == table_len)
+		high = low = i - 1;
 	else
-		high = i; /* i.e. i == 0 */
-	low = i;
+		high = (low = i) - 1;
 
 	return fixp_linear_interpolate(table[low].ocv,
 				       table[low].capacity,