[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1567d831e04c3e2fcb9e18dd36b7bcba4634581a.1766268280.git.waqar.hameed@axis.com>
Date: Sat, 20 Dec 2025 23:36:02 +0100
From: Waqar Hameed <waqar.hameed@...s.com>
To: Sebastian Reichel <sre@...nel.org>, Krzysztof Kozlowski <krzk@...nel.org>,
Anda-Maria Nicolae <anda-maria.nicolae@...el.com>
CC: <kernel@...s.com>, <linux-pm@...r.kernel.org>,
<linux-kernel@...r.kernel.org>
Subject: [PATCH 10/11] power: supply: rt9455: 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: e86d69dd786e ("power_supply: Add support for Richtek RT9455 battery charger")
Signed-off-by: Waqar Hameed <waqar.hameed@...s.com>
---
drivers/power/supply/rt9455_charger.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/drivers/power/supply/rt9455_charger.c b/drivers/power/supply/rt9455_charger.c
index 1ffe7f02932f6..5130d2395e88f 100644
--- a/drivers/power/supply/rt9455_charger.c
+++ b/drivers/power/supply/rt9455_charger.c
@@ -1663,6 +1663,15 @@ static int rt9455_probe(struct i2c_client *client)
rt9455_charger_config.supplied_to = rt9455_charger_supplied_to;
rt9455_charger_config.num_supplicants =
ARRAY_SIZE(rt9455_charger_supplied_to);
+
+ info->charger = devm_power_supply_register(dev, &rt9455_charger_desc,
+ &rt9455_charger_config);
+ if (IS_ERR(info->charger)) {
+ dev_err(dev, "Failed to register charger\n");
+ ret = PTR_ERR(info->charger);
+ goto put_usb_notifier;
+ }
+
ret = devm_request_threaded_irq(dev, client->irq, NULL,
rt9455_irq_handler_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
@@ -1678,14 +1687,6 @@ static int rt9455_probe(struct i2c_client *client)
goto put_usb_notifier;
}
- info->charger = devm_power_supply_register(dev, &rt9455_charger_desc,
- &rt9455_charger_config);
- if (IS_ERR(info->charger)) {
- dev_err(dev, "Failed to register charger\n");
- ret = PTR_ERR(info->charger);
- goto put_usb_notifier;
- }
-
return 0;
put_usb_notifier:
--
2.39.5
Powered by blists - more mailing lists