Skip to content

Commit 838767f

Browse files
whamesre
authored andcommitted
power: supply: pf1550: Fix use-after-free in power_supply_changed()
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: 4b6b643 ("power: supply: pf1550: add battery charger support") Signed-off-by: Waqar Hameed <waqar.hameed@axis.com> Reviewed-by: Samuel Kayode <samkay014@gmail.com> Link: https://patch.msgid.link/ae5a71b7e4dd2967d8fdcc531065cc71b17c86f5.1766268280.git.waqar.hameed@axis.com Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
1 parent b2ce982 commit 838767f

1 file changed

Lines changed: 16 additions & 16 deletions

File tree

drivers/power/supply/pf1550-charger.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -584,22 +584,6 @@ static int pf1550_charger_probe(struct platform_device *pdev)
584584
return dev_err_probe(chg->dev, ret,
585585
"failed to add battery sense work\n");
586586

587-
for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) {
588-
irq = platform_get_irq(pdev, i);
589-
if (irq < 0)
590-
return irq;
591-
592-
chg->virqs[i] = irq;
593-
594-
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
595-
pf1550_charger_irq_handler,
596-
IRQF_NO_SUSPEND,
597-
"pf1550-charger", chg);
598-
if (ret)
599-
return dev_err_probe(&pdev->dev, ret,
600-
"failed irq request\n");
601-
}
602-
603587
psy_cfg.drv_data = chg;
604588

605589
chg->charger = devm_power_supply_register(&pdev->dev,
@@ -616,6 +600,22 @@ static int pf1550_charger_probe(struct platform_device *pdev)
616600
return dev_err_probe(&pdev->dev, PTR_ERR(chg->battery),
617601
"failed: power supply register\n");
618602

603+
for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) {
604+
irq = platform_get_irq(pdev, i);
605+
if (irq < 0)
606+
return irq;
607+
608+
chg->virqs[i] = irq;
609+
610+
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
611+
pf1550_charger_irq_handler,
612+
IRQF_NO_SUSPEND,
613+
"pf1550-charger", chg);
614+
if (ret)
615+
return dev_err_probe(&pdev->dev, ret,
616+
"failed irq request\n");
617+
}
618+
619619
pf1550_dt_parse_dev_info(chg);
620620

621621
return pf1550_reg_init(chg);

0 commit comments

Comments
 (0)