Skip to content

Commit

Permalink
power: generic-adc-battery: fix out-of-bounds write when copying chan…
Browse files Browse the repository at this point in the history
…nel properties

commit 932d474 upstream.

We did have sporadic problems in the pinctrl framework during boot
where a pin group name unexpectedly became NULL leading to a NULL
dereference in strcmp.

Detailled analysis of the failing cases did reveal that there were
two devm allocated objects close to each other. The second one was
the affected group_desc in pinmux and the first one was the
psy_desc->properties buffer of the gab driver.

Review of the gab code showed that the address calculation for
one memcpy() is wrong. It does

	properties + sizeof(type) * index

but C is defined to do the index multiplication already for
pointer + integer additions. Hence the factor was applied twice
and the memcpy() does write outside of the properties buffer.
Sometimes it happened to be the pinctrl and triggered the strcmp(NULL).

Anyways, it is overkill to use a memcpy() here instead of a simple
assignment, which is easier to read and has less risk for wrong
address calculations. So we change code to a simple assignment.

If we initialize the index to the first free location, we can even
remove the local variable 'properties'.

This bug seems to exist right from the beginning in 3.7-rc1 in

commit e60fea7 ("power: battery: Generic battery driver using IIO")

Signed-off-by: H. Nikolaus Schaller <hns@goldelico.com>
Cc: stable@vger.kernel.org
Fixes: e60fea7 ("power: battery: Generic battery driver using IIO")
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
H. Nikolaus Schaller authored and Greg Kroah-Hartman committed Sep 5, 2018
1 parent 86b0dd9 commit 7ffb7b7
Showing 1 changed file with 4 additions and 10 deletions.
14 changes: 4 additions & 10 deletions drivers/power/supply/generic-adc-battery.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,10 +241,9 @@ static int gab_probe(struct platform_device *pdev)
struct power_supply_desc *psy_desc;
struct power_supply_config psy_cfg = {};
struct gab_platform_data *pdata = pdev->dev.platform_data;
enum power_supply_property *properties;
int ret = 0;
int chan;
int index = 0;
int index = ARRAY_SIZE(gab_props);

adc_bat = devm_kzalloc(&pdev->dev, sizeof(*adc_bat), GFP_KERNEL);
if (!adc_bat) {
Expand Down Expand Up @@ -278,8 +277,6 @@ static int gab_probe(struct platform_device *pdev)
}

memcpy(psy_desc->properties, gab_props, sizeof(gab_props));
properties = (enum power_supply_property *)
((char *)psy_desc->properties + sizeof(gab_props));

/*
* getting channel from iio and copying the battery properties
Expand All @@ -293,15 +290,12 @@ static int gab_probe(struct platform_device *pdev)
adc_bat->channel[chan] = NULL;
} else {
/* copying properties for supported channels only */
memcpy(properties + sizeof(*(psy_desc->properties)) * index,
&gab_dyn_props[chan],
sizeof(gab_dyn_props[chan]));
index++;
psy_desc->properties[index++] = gab_dyn_props[chan];
}
}

/* none of the channels are supported so let's bail out */
if (index == 0) {
if (index == ARRAY_SIZE(gab_props)) {
ret = -ENODEV;
goto second_mem_fail;
}
Expand All @@ -312,7 +306,7 @@ static int gab_probe(struct platform_device *pdev)
* as come channels may be not be supported by the device.So
* we need to take care of that.
*/
psy_desc->num_properties = ARRAY_SIZE(gab_props) + index;
psy_desc->num_properties = index;

adc_bat->psy = power_supply_register(&pdev->dev, psy_desc, &psy_cfg);
if (IS_ERR(adc_bat->psy)) {
Expand Down

0 comments on commit 7ffb7b7

Please sign in to comment.