]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
power: supply: wm97xx: Fix NULL pointer dereference in power_supply_changed()
authorWaqar Hameed <waqar.hameed@axis.com>
Sat, 20 Dec 2025 22:46:24 +0000 (23:46 +0100)
committerSebastian Reichel <sebastian.reichel@collabora.com>
Mon, 12 Jan 2026 01:52:32 +0000 (02:52 +0100)
In `probe()`, `request_irq()` is called before allocating/registering a
`power_supply` handle. If an interrupt is fired between the call to
`request_irq()` and `power_supply_register()`, the `power_supply` handle
will be used uninitialized in `power_supply_changed()` in
`wm97xx_bat_update()` (triggered from the interrupt handler). This will
lead to a `NULL` pointer dereference since

Fix this racy `NULL` pointer dereference by making sure the IRQ is
requested _after_ the registration of the `power_supply` handle. Since
the IRQ is the last thing requests in the `probe()` now, remove the
error path for freeing it. Instead add one for unregistering the
`power_supply` handle when IRQ request fails.

Fixes: 7c87942aef52 ("wm97xx_battery: Use irq to detect charger state")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
Link: https://patch.msgid.link/97b55f0479a932eea7213844bf66f28a974e27a2.1766270196.git.waqar.hameed@axis.com
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
drivers/power/supply/wm97xx_battery.c

index b3b0c37a9dd2d5bc0a3dbabb16897db6fd6c9879..f00722c88c6fea7d6204c0504ecf810f1668c344 100644 (file)
@@ -178,12 +178,6 @@ static int wm97xx_bat_probe(struct platform_device *dev)
                                     "failed to get charge GPIO\n");
        if (charge_gpiod) {
                gpiod_set_consumer_name(charge_gpiod, "BATT CHRG");
-               ret = request_irq(gpiod_to_irq(charge_gpiod),
-                               wm97xx_chrg_irq, 0,
-                               "AC Detect", dev);
-               if (ret)
-                       return dev_err_probe(&dev->dev, ret,
-                                            "failed to request GPIO irq\n");
                props++;        /* POWER_SUPPLY_PROP_STATUS */
        }
 
@@ -199,10 +193,8 @@ static int wm97xx_bat_probe(struct platform_device *dev)
                props++;        /* POWER_SUPPLY_PROP_VOLTAGE_MIN */
 
        prop = kcalloc(props, sizeof(*prop), GFP_KERNEL);
-       if (!prop) {
-               ret = -ENOMEM;
-               goto err3;
-       }
+       if (!prop)
+               return -ENOMEM;
 
        prop[i++] = POWER_SUPPLY_PROP_PRESENT;
        if (charge_gpiod)
@@ -236,15 +228,27 @@ static int wm97xx_bat_probe(struct platform_device *dev)
                schedule_work(&bat_work);
        } else {
                ret = PTR_ERR(bat_psy);
-               goto err4;
+               goto free;
+       }
+
+       if (charge_gpiod) {
+               ret = request_irq(gpiod_to_irq(charge_gpiod), wm97xx_chrg_irq,
+                                 0, "AC Detect", dev);
+               if (ret) {
+                       dev_err_probe(&dev->dev, ret,
+                                     "failed to request GPIO irq\n");
+                       goto unregister;
+               }
        }
 
        return 0;
-err4:
+
+unregister:
+       power_supply_unregister(bat_psy);
+
+free:
        kfree(prop);
-err3:
-       if (charge_gpiod)
-               free_irq(gpiod_to_irq(charge_gpiod), dev);
+
        return ret;
 }