]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
power: supply: ds2782: fix possible use-after-free on remove
authorSven Van Asbroeck <thesven73@gmail.com>
Tue, 12 Feb 2019 16:21:49 +0000 (11:21 -0500)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Tue, 12 Feb 2019 22:27:16 +0000 (23:27 +0100)
In remove(), use cancel_delayed_work_sync() to cancel the
delayed work. Otherwise there's a chance that this work
will continue to run until after the device has been removed.

While we're here, fix the deallocation order in remove(),
to correspond to the inverse of the probe() allocation
order. This guarantees that any remaining work can run
to completion with all driver structures still intact.

This issue was detected with the help of Coccinelle.

Signed-off-by: Sven Van Asbroeck <TheSven73@gmail.com>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/ds2782_battery.c

index 019c58493e3d5a833b48b3b4256c6ebbd8440455..04b0fe7d7d625c2fa9dc4cb86f71df7af3e83b86 100644 (file)
@@ -319,17 +319,17 @@ static void ds278x_power_supply_init(struct power_supply_desc *battery)
 static int ds278x_battery_remove(struct i2c_client *client)
 {
        struct ds278x_info *info = i2c_get_clientdata(client);
+       int id = info->id;
 
        power_supply_unregister(info->battery);
+       cancel_delayed_work_sync(&info->bat_work);
        kfree(info->battery_desc.name);
+       kfree(info);
 
        mutex_lock(&battery_lock);
-       idr_remove(&battery_id, info->id);
+       idr_remove(&battery_id, id);
        mutex_unlock(&battery_lock);
 
-       cancel_delayed_work(&info->bat_work);
-
-       kfree(info);
        return 0;
 }