Skip to content
/ linux Public

Commit a39f8f0

Browse files
whameSasha Levin
authored andcommitted
power: supply: rt9455: Fix use-after-free in power_supply_changed()
[ Upstream commit e2febe3 ] Using the `devm_` variant for requesting IRQ _before_ the `devm_` variant for allocating/registering the `power_supply` handle, means that the `power_supply` handle will be deallocated/unregistered _before_ the interrupt handler (since `devm_` naturally deallocates in reverse allocation order). This means that during removal, there is a race condition where an interrupt can fire just _after_ the `power_supply` handle has been freed, *but* just _before_ the corresponding unregistration of the IRQ handler has run. This will lead to the IRQ handler calling `power_supply_changed()` with a freed `power_supply` handle. Which usually crashes the system or otherwise silently corrupts the memory... Note that there is a similar situation which can also happen during `probe()`; the possibility of an interrupt firing _before_ registering the `power_supply` handle. This would then lead to the nasty situation of using the `power_supply` handle *uninitialized* in `power_supply_changed()`. Fix this racy use-after-free by making sure the IRQ is requested _after_ the registration of the `power_supply` handle. Fixes: e86d69d ("power_supply: Add support for Richtek RT9455 battery charger") Signed-off-by: Waqar Hameed <waqar.hameed@axis.com> Link: https://patch.msgid.link/1567d831e04c3e2fcb9e18dd36b7bcba4634581a.1766268280.git.waqar.hameed@axis.com Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 33751e2 commit a39f8f0

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

drivers/power/supply/rt9455_charger.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,15 @@ static int rt9455_probe(struct i2c_client *client,
16651665
rt9455_charger_config.supplied_to = rt9455_charger_supplied_to;
16661666
rt9455_charger_config.num_supplicants =
16671667
ARRAY_SIZE(rt9455_charger_supplied_to);
1668+
1669+
info->charger = devm_power_supply_register(dev, &rt9455_charger_desc,
1670+
&rt9455_charger_config);
1671+
if (IS_ERR(info->charger)) {
1672+
dev_err(dev, "Failed to register charger\n");
1673+
ret = PTR_ERR(info->charger);
1674+
goto put_usb_notifier;
1675+
}
1676+
16681677
ret = devm_request_threaded_irq(dev, client->irq, NULL,
16691678
rt9455_irq_handler_thread,
16701679
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
@@ -1680,14 +1689,6 @@ static int rt9455_probe(struct i2c_client *client,
16801689
goto put_usb_notifier;
16811690
}
16821691

1683-
info->charger = devm_power_supply_register(dev, &rt9455_charger_desc,
1684-
&rt9455_charger_config);
1685-
if (IS_ERR(info->charger)) {
1686-
dev_err(dev, "Failed to register charger\n");
1687-
ret = PTR_ERR(info->charger);
1688-
goto put_usb_notifier;
1689-
}
1690-
16911692
return 0;
16921693

16931694
put_usb_notifier:

0 commit comments

Comments
 (0)