Skip to content

Commit 8e59c7f

Browse files
krzksre
authored andcommitted
power_supply: Fix NULL pointer dereference during bq27x00_battery probe
Power supply is often registered during probe of a driver. The power_supply_register() returns pointer to newly allocated structure as return value. However before returning the power_supply_register() calls back the get_property() method provided by the driver through uevent. In that time the driver probe is still in progress and driver did not assigned pointer to power supply to its local variables. This leads to NULL pointer dereference from get_property() function. Starting from bq27x00_battery_probe(): di->bat = power_supply_register() device_add() kobject_uevent() power_supply_uevent() power_supply_show_property() power_supply_get_property() bq27x00_battery_get_property() dereference of (di->bat) which is NULL here The first uevent of power supply (the one coming from device creation) should not call back to the driver. To prevent that from happening, increment the atomic use counter at the end of power_supply_register(). This means that power_supply_get_property() will return -ENODEV. IMPORTANT: The patch has impact on this first uevent sent from power supply because it will not contain properties from power supply. The uevent with properties will be sent later after indicating that power supply has changed. This also has a race now, but will be fixed in other patches. Reported-by: H. Nikolaus Schaller <[email protected]> Signed-off-by: Krzysztof Kozlowski <[email protected]> Fixes: 297d716 ("power_supply: Change ownership from driver to core") Tested-By: Dr. H. Nikolaus Schaller <[email protected]> Signed-off-by: Sebastian Reichel <[email protected]>
1 parent e260818 commit 8e59c7f

File tree

1 file changed

+10
-1
lines changed

1 file changed

+10
-1
lines changed

drivers/power/power_supply_core.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,6 @@ __power_supply_register(struct device *parent,
659659
dev->release = power_supply_dev_release;
660660
dev_set_drvdata(dev, psy);
661661
psy->desc = desc;
662-
atomic_inc(&psy->use_cnt);
663662
if (cfg) {
664663
psy->drv_data = cfg->drv_data;
665664
psy->of_node = cfg->of_node;
@@ -700,6 +699,16 @@ __power_supply_register(struct device *parent,
700699
if (rc)
701700
goto create_triggers_failed;
702701

702+
/*
703+
* Update use_cnt after any uevents (most notably from device_add()).
704+
* We are here still during driver's probe but
705+
* the power_supply_uevent() calls back driver's get_property
706+
* method so:
707+
* 1. Driver did not assigned the returned struct power_supply,
708+
* 2. Driver could not finish initialization (anything in its probe
709+
* after calling power_supply_register()).
710+
*/
711+
atomic_inc(&psy->use_cnt);
703712
power_supply_changed(psy);
704713

705714
return psy;

0 commit comments

Comments
 (0)