Skip to content
/ linux Public

Commit 697bb5d

Browse files
whameSasha Levin
authored andcommitted
power: supply: act8945a: Fix use-after-free in power_supply_changed()
[ Upstream commit 3291c51 ] 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: a09209a ("power: supply: act8945a_charger: Add status change update support") Signed-off-by: Waqar Hameed <waqar.hameed@axis.com> Link: https://patch.msgid.link/bcf3a23b5187df0bba54a8c8fe09f8b8a0031dee.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 f50433f commit 697bb5d

File tree

1 file changed

+8
-8
lines changed

1 file changed

+8
-8
lines changed

drivers/power/supply/act8945a_charger.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -597,14 +597,6 @@ static int act8945a_charger_probe(struct platform_device *pdev)
597597
return irq ?: -ENXIO;
598598
}
599599

600-
ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
601-
IRQF_TRIGGER_FALLING, "act8945a_interrupt",
602-
charger);
603-
if (ret) {
604-
dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n");
605-
return ret;
606-
}
607-
608600
charger->desc.name = "act8945a-charger";
609601
charger->desc.get_property = act8945a_charger_get_property;
610602
charger->desc.properties = act8945a_charger_props;
@@ -625,6 +617,14 @@ static int act8945a_charger_probe(struct platform_device *pdev)
625617
return PTR_ERR(charger->psy);
626618
}
627619

620+
ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
621+
IRQF_TRIGGER_FALLING, "act8945a_interrupt",
622+
charger);
623+
if (ret) {
624+
dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n");
625+
return ret;
626+
}
627+
628628
platform_set_drvdata(pdev, charger);
629629

630630
INIT_WORK(&charger->work, act8945a_work);

0 commit comments

Comments
 (0)