Skip to content
/ linux Public

Commit 2178dc6

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 dbe579e commit 2178dc6

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
@@ -1663,6 +1663,15 @@ static int rt9455_probe(struct i2c_client *client)
16631663
rt9455_charger_config.supplied_to = rt9455_charger_supplied_to;
16641664
rt9455_charger_config.num_supplicants =
16651665
ARRAY_SIZE(rt9455_charger_supplied_to);
1666+
1667+
info->charger = devm_power_supply_register(dev, &rt9455_charger_desc,
1668+
&rt9455_charger_config);
1669+
if (IS_ERR(info->charger)) {
1670+
dev_err(dev, "Failed to register charger\n");
1671+
ret = PTR_ERR(info->charger);
1672+
goto put_usb_notifier;
1673+
}
1674+
16661675
ret = devm_request_threaded_irq(dev, client->irq, NULL,
16671676
rt9455_irq_handler_thread,
16681677
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
@@ -1678,14 +1687,6 @@ static int rt9455_probe(struct i2c_client *client)
16781687
goto put_usb_notifier;
16791688
}
16801689

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

16911692
put_usb_notifier:

0 commit comments

Comments
 (0)