* [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed()
@ 2025-12-20 22:35 Waqar Hameed
2025-12-20 22:35 ` [PATCH 01/11] power: supply: ab8500: " Waqar Hameed
` (10 more replies)
0 siblings, 11 replies; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:35 UTC (permalink / raw)
To: Linus Walleij, Sebastian Reichel, Samuel Kayode, Wenyou Yang,
Ricardo Rivera-Matos, Dan Murphy, Tony Lindgren, Mike A. Chan,
Jun Nakajima, Xiaohui Xin, Yunhong Jiang, Tom Keel, Frank Li,
Lee Jones, Nikita Travkin, Anda-Maria Nicolae,
Krzysztof Kozlowski, Phil Reid, Alan Cox, Sheng Yang
Cc: linux-pm, linux-kernel, imx
The majority of the drivers in `drivers/power/supply/` do the right
thing when registering an interrupt handler and the `power_supply`
handle; namely making sure that the interrupt handler only runs while
the `power_supply` handle is valid. The drivers in this patch series do
not however. This can lead to a nasty use-after-free as thoroughly
explained in the commit message.
These were identified by grepping for `request.+irq` and
`power_supply_changed\(`, and then manually inspecting and fixing the
affected ones. This issue was found when writing a new driver for the
upcoming TI BQ25630 [1]. Patch adding support for that one will be sent
as soon as TI releases the datasheet publicly, which should be anytime
soon...
[1] https://www.ti.com/product/BQ25630
Waqar Hameed (11):
power: supply: ab8500: Fix use-after-free in power_supply_changed()
power: supply: act8945a: Fix use-after-free in power_supply_changed()
power: supply: bq256xx: Fix use-after-free in power_supply_changed()
power: supply: bq25980: Fix use-after-free in power_supply_changed()
power: supply: cpcap-battery: Fix use-after-free in
power_supply_changed()
power: supply: goldfish: Fix use-after-free in power_supply_changed()
power: supply: pf1550: Fix use-after-free in power_supply_changed()
power: supply: pm8916_bms_vm: Fix use-after-free in
power_supply_changed()
power: supply: pm8916_lbc: Fix use-after-free in
power_supply_changed()
power: supply: rt9455: Fix use-after-free in power_supply_changed()
power: supply: sbs-battery: Fix use-after-free in
power_supply_changed()
drivers/power/supply/ab8500_charger.c | 40 ++++++++++++-------------
drivers/power/supply/act8945a_charger.c | 16 +++++-----
drivers/power/supply/bq256xx_charger.c | 12 ++++----
drivers/power/supply/bq25980_charger.c | 12 ++++----
drivers/power/supply/cpcap-battery.c | 8 ++---
drivers/power/supply/goldfish_battery.c | 12 ++++----
drivers/power/supply/pf1550-charger.c | 32 ++++++++++----------
drivers/power/supply/pm8916_bms_vm.c | 18 +++++------
drivers/power/supply/pm8916_lbc.c | 18 +++++------
drivers/power/supply/rt9455_charger.c | 17 ++++++-----
drivers/power/supply/sbs-battery.c | 36 +++++++++++-----------
11 files changed, 111 insertions(+), 110 deletions(-)
base-commit: fa084c35afa13ab07a860ef0936cd987f9aa0460
--
2.39.5
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 01/11] power: supply: ab8500: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
@ 2025-12-20 22:35 ` Waqar Hameed
2025-12-22 22:35 ` Linus Walleij
2025-12-20 22:35 ` [PATCH 02/11] power: supply: act8945a: " Waqar Hameed
` (9 subsequent siblings)
10 siblings, 1 reply; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:35 UTC (permalink / raw)
To: Linus Walleij, Sebastian Reichel; +Cc: kernel, linux-pm, linux-kernel
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()`.
Commit 1c1f13a006ed ("power: supply: ab8500: Move to componentized
binding") introduced this issue during a refactorization. Fix this racy
use-after-free by making sure the IRQ is requested _after_ the
registration of the `power_supply` handle.
Fixes: 1c1f13a006ed ("power: supply: ab8500: Move to componentized binding")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/ab8500_charger.c | 40 +++++++++++++--------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c
index 5f4537766e5b9..1813fbdfa1c1f 100644
--- a/drivers/power/supply/ab8500_charger.c
+++ b/drivers/power/supply/ab8500_charger.c
@@ -3466,26 +3466,6 @@ static int ab8500_charger_probe(struct platform_device *pdev)
return ret;
}
- /* Request interrupts */
- for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
- irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
- if (irq < 0)
- return irq;
-
- ret = devm_request_threaded_irq(dev,
- irq, NULL, ab8500_charger_irq[i].isr,
- IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
- ab8500_charger_irq[i].name, di);
-
- if (ret != 0) {
- dev_err(dev, "failed to request %s IRQ %d: %d\n"
- , ab8500_charger_irq[i].name, irq, ret);
- return ret;
- }
- dev_dbg(dev, "Requested %s IRQ %d: %d\n",
- ab8500_charger_irq[i].name, irq, ret);
- }
-
/* initialize lock */
spin_lock_init(&di->usb_state.usb_lock);
mutex_init(&di->usb_ipt_crnt_lock);
@@ -3614,6 +3594,26 @@ static int ab8500_charger_probe(struct platform_device *pdev)
return PTR_ERR(di->usb_chg.psy);
}
+ /* Request interrupts */
+ for (i = 0; i < ARRAY_SIZE(ab8500_charger_irq); i++) {
+ irq = platform_get_irq_byname(pdev, ab8500_charger_irq[i].name);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(dev,
+ irq, NULL, ab8500_charger_irq[i].isr,
+ IRQF_SHARED | IRQF_NO_SUSPEND | IRQF_ONESHOT,
+ ab8500_charger_irq[i].name, di);
+
+ if (ret != 0) {
+ dev_err(dev, "failed to request %s IRQ %d: %d\n"
+ , ab8500_charger_irq[i].name, irq, ret);
+ return ret;
+ }
+ dev_dbg(dev, "Requested %s IRQ %d: %d\n",
+ ab8500_charger_irq[i].name, irq, ret);
+ }
+
/*
* Check what battery we have, since we always have the USB
* psy, use that as a handle.
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 02/11] power: supply: act8945a: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
2025-12-20 22:35 ` [PATCH 01/11] power: supply: ab8500: " Waqar Hameed
@ 2025-12-20 22:35 ` Waqar Hameed
2025-12-20 22:35 ` [PATCH 03/11] power: supply: bq256xx: " Waqar Hameed
` (8 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:35 UTC (permalink / raw)
To: Sebastian Reichel, Wenyou Yang; +Cc: kernel, linux-pm, linux-kernel
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: a09209acd6a8 ("power: supply: act8945a_charger: Add status change update support")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/act8945a_charger.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/power/supply/act8945a_charger.c b/drivers/power/supply/act8945a_charger.c
index 3901a02f326a5..9dec4486b1439 100644
--- a/drivers/power/supply/act8945a_charger.c
+++ b/drivers/power/supply/act8945a_charger.c
@@ -597,14 +597,6 @@ static int act8945a_charger_probe(struct platform_device *pdev)
return irq ?: -ENXIO;
}
- ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
- IRQF_TRIGGER_FALLING, "act8945a_interrupt",
- charger);
- if (ret) {
- dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n");
- return ret;
- }
-
charger->desc.name = "act8945a-charger";
charger->desc.get_property = act8945a_charger_get_property;
charger->desc.properties = act8945a_charger_props;
@@ -625,6 +617,14 @@ static int act8945a_charger_probe(struct platform_device *pdev)
return PTR_ERR(charger->psy);
}
+ ret = devm_request_irq(&pdev->dev, irq, act8945a_status_changed,
+ IRQF_TRIGGER_FALLING, "act8945a_interrupt",
+ charger);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request nIRQ pin IRQ\n");
+ return ret;
+ }
+
platform_set_drvdata(pdev, charger);
INIT_WORK(&charger->work, act8945a_work);
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/11] power: supply: bq25980: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (2 preceding siblings ...)
2025-12-20 22:35 ` [PATCH 03/11] power: supply: bq256xx: " Waqar Hameed
@ 2025-12-20 22:35 ` Waqar Hameed
2025-12-20 22:36 ` [PATCH 06/11] power: supply: goldfish: " Waqar Hameed
` (6 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:35 UTC (permalink / raw)
To: Sebastian Reichel, Dan Murphy; +Cc: kernel, linux-pm, linux-kernel
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: 5069185fc18e ("power: supply: bq25980: Add support for the BQ259xx family")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/bq25980_charger.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/power/supply/bq25980_charger.c b/drivers/power/supply/bq25980_charger.c
index 723858d62d141..73f06f09f134c 100644
--- a/drivers/power/supply/bq25980_charger.c
+++ b/drivers/power/supply/bq25980_charger.c
@@ -1241,6 +1241,12 @@ static int bq25980_probe(struct i2c_client *client)
return ret;
}
+ ret = bq25980_power_supply_init(bq, dev);
+ if (ret) {
+ dev_err(dev, "Failed to register power supply\n");
+ return ret;
+ }
+
if (client->irq) {
ret = devm_request_threaded_irq(dev, client->irq, NULL,
bq25980_irq_handler_thread,
@@ -1251,12 +1257,6 @@ static int bq25980_probe(struct i2c_client *client)
return ret;
}
- ret = bq25980_power_supply_init(bq, dev);
- if (ret) {
- dev_err(dev, "Failed to register power supply\n");
- return ret;
- }
-
ret = bq25980_hw_init(bq);
if (ret) {
dev_err(dev, "Cannot initialize the chip.\n");
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/11] power: supply: bq256xx: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
2025-12-20 22:35 ` [PATCH 01/11] power: supply: ab8500: " Waqar Hameed
2025-12-20 22:35 ` [PATCH 02/11] power: supply: act8945a: " Waqar Hameed
@ 2025-12-20 22:35 ` Waqar Hameed
2025-12-20 22:35 ` [PATCH 04/11] power: supply: bq25980: " Waqar Hameed
` (7 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:35 UTC (permalink / raw)
To: Sebastian Reichel, Ricardo Rivera-Matos; +Cc: kernel, linux-pm, linux-kernel
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: 32e4978bb920 ("power: supply: bq256xx: Introduce the BQ256XX charger driver")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/bq256xx_charger.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/power/supply/bq256xx_charger.c b/drivers/power/supply/bq256xx_charger.c
index ae14162f017a9..d3de4f8b80db1 100644
--- a/drivers/power/supply/bq256xx_charger.c
+++ b/drivers/power/supply/bq256xx_charger.c
@@ -1741,6 +1741,12 @@ static int bq256xx_probe(struct i2c_client *client)
usb_register_notifier(bq->usb3_phy, &bq->usb_nb);
}
+ ret = bq256xx_power_supply_init(bq, &psy_cfg, dev);
+ if (ret) {
+ dev_err(dev, "Failed to register power supply\n");
+ return ret;
+ }
+
if (client->irq) {
ret = devm_request_threaded_irq(dev, client->irq, NULL,
bq256xx_irq_handler_thread,
@@ -1753,12 +1759,6 @@ static int bq256xx_probe(struct i2c_client *client)
}
}
- ret = bq256xx_power_supply_init(bq, &psy_cfg, dev);
- if (ret) {
- dev_err(dev, "Failed to register power supply\n");
- return ret;
- }
-
ret = bq256xx_hw_init(bq);
if (ret) {
dev_err(dev, "Cannot initialize the chip.\n");
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/11] power: supply: cpcap-battery: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (4 preceding siblings ...)
2025-12-20 22:36 ` [PATCH 06/11] power: supply: goldfish: " Waqar Hameed
@ 2025-12-20 22:36 ` Waqar Hameed
2025-12-20 22:36 ` [PATCH 08/11] power: supply: pm8916_bms_vm: " Waqar Hameed
` (4 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:36 UTC (permalink / raw)
To: Sebastian Reichel, Tony Lindgren; +Cc: kernel, linux-pm, linux-kernel
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: 874b2adbed12 ("power: supply: cpcap-battery: Add a battery driver")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/cpcap-battery.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/power/supply/cpcap-battery.c b/drivers/power/supply/cpcap-battery.c
index 8106d1edcbc26..507fdc1c866d5 100644
--- a/drivers/power/supply/cpcap-battery.c
+++ b/drivers/power/supply/cpcap-battery.c
@@ -1122,10 +1122,6 @@ static int cpcap_battery_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ddata);
- error = cpcap_battery_init_interrupts(pdev, ddata);
- if (error)
- return error;
-
error = cpcap_battery_init_iio(ddata);
if (error)
return error;
@@ -1142,6 +1138,10 @@ static int cpcap_battery_probe(struct platform_device *pdev)
return error;
}
+ error = cpcap_battery_init_interrupts(pdev, ddata);
+ if (error)
+ return error;
+
atomic_set(&ddata->active, 1);
error = cpcap_battery_calibrate(ddata);
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 06/11] power: supply: goldfish: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (3 preceding siblings ...)
2025-12-20 22:35 ` [PATCH 04/11] power: supply: bq25980: " Waqar Hameed
@ 2025-12-20 22:36 ` Waqar Hameed
2025-12-20 22:36 ` [PATCH 05/11] power: supply: cpcap-battery: " Waqar Hameed
` (5 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:36 UTC (permalink / raw)
To: Sebastian Reichel, Mike A. Chan, Alan Cox, Tom Keel,
Yunhong Jiang, Sheng Yang
Cc: kernel, Bruce Beare, Anton Vorontsov, Jun Nakajima, linux-pm,
linux-kernel
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: 84d7b7687489 ("power: Add battery driver for goldfish emulator")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/goldfish_battery.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/power/supply/goldfish_battery.c b/drivers/power/supply/goldfish_battery.c
index 479195e35d734..5aa24e4dc4455 100644
--- a/drivers/power/supply/goldfish_battery.c
+++ b/drivers/power/supply/goldfish_battery.c
@@ -224,12 +224,6 @@ static int goldfish_battery_probe(struct platform_device *pdev)
if (data->irq < 0)
return -ENODEV;
- ret = devm_request_irq(&pdev->dev, data->irq,
- goldfish_battery_interrupt,
- IRQF_SHARED, pdev->name, data);
- if (ret)
- return ret;
-
psy_cfg.drv_data = data;
data->ac = devm_power_supply_register(&pdev->dev,
@@ -244,6 +238,12 @@ static int goldfish_battery_probe(struct platform_device *pdev)
if (IS_ERR(data->battery))
return PTR_ERR(data->battery);
+ ret = devm_request_irq(&pdev->dev, data->irq,
+ goldfish_battery_interrupt,
+ IRQF_SHARED, pdev->name, data);
+ if (ret)
+ return ret;
+
GOLDFISH_BATTERY_WRITE(data, BATTERY_INT_ENABLE, BATTERY_INT_MASK);
return 0;
}
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 07/11] power: supply: pf1550: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (6 preceding siblings ...)
2025-12-20 22:36 ` [PATCH 08/11] power: supply: pm8916_bms_vm: " Waqar Hameed
@ 2025-12-20 22:36 ` Waqar Hameed
2026-01-06 2:59 ` Samuel Kayode
2025-12-20 22:36 ` [PATCH 09/11] power: supply: pm8916_lbc: " Waqar Hameed
` (2 subsequent siblings)
10 siblings, 1 reply; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:36 UTC (permalink / raw)
To: Samuel Kayode, Sebastian Reichel, Frank Li, Lee Jones
Cc: kernel, imx, linux-pm, linux-kernel
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: 4b6b6433a97d ("power: supply: pf1550: add battery charger support")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/pf1550-charger.c | 32 +++++++++++++--------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/power/supply/pf1550-charger.c b/drivers/power/supply/pf1550-charger.c
index 98f1ee8eca3bc..a457862ef4610 100644
--- a/drivers/power/supply/pf1550-charger.c
+++ b/drivers/power/supply/pf1550-charger.c
@@ -584,22 +584,6 @@ static int pf1550_charger_probe(struct platform_device *pdev)
return dev_err_probe(chg->dev, ret,
"failed to add battery sense work\n");
- for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) {
- irq = platform_get_irq(pdev, i);
- if (irq < 0)
- return irq;
-
- chg->virqs[i] = irq;
-
- ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
- pf1550_charger_irq_handler,
- IRQF_NO_SUSPEND,
- "pf1550-charger", chg);
- if (ret)
- return dev_err_probe(&pdev->dev, ret,
- "failed irq request\n");
- }
-
psy_cfg.drv_data = chg;
chg->charger = devm_power_supply_register(&pdev->dev,
@@ -616,6 +600,22 @@ static int pf1550_charger_probe(struct platform_device *pdev)
return dev_err_probe(&pdev->dev, PTR_ERR(chg->battery),
"failed: power supply register\n");
+ for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) {
+ irq = platform_get_irq(pdev, i);
+ if (irq < 0)
+ return irq;
+
+ chg->virqs[i] = irq;
+
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ pf1550_charger_irq_handler,
+ IRQF_NO_SUSPEND,
+ "pf1550-charger", chg);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed irq request\n");
+ }
+
pf1550_dt_parse_dev_info(chg);
return pf1550_reg_init(chg);
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 08/11] power: supply: pm8916_bms_vm: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (5 preceding siblings ...)
2025-12-20 22:36 ` [PATCH 05/11] power: supply: cpcap-battery: " Waqar Hameed
@ 2025-12-20 22:36 ` Waqar Hameed
2025-12-21 5:47 ` Nikita Travkin
2025-12-20 22:36 ` [PATCH 07/11] power: supply: pf1550: " Waqar Hameed
` (3 subsequent siblings)
10 siblings, 1 reply; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:36 UTC (permalink / raw)
To: Sebastian Reichel, Nikita Travkin; +Cc: kernel, linux-pm, linux-kernel
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: 098bce1838e0 ("power: supply: Add pm8916 VM-BMS support")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/pm8916_bms_vm.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/power/supply/pm8916_bms_vm.c b/drivers/power/supply/pm8916_bms_vm.c
index 5120be086e6ff..de5d571c03e21 100644
--- a/drivers/power/supply/pm8916_bms_vm.c
+++ b/drivers/power/supply/pm8916_bms_vm.c
@@ -167,15 +167,6 @@ static int pm8916_bms_vm_battery_probe(struct platform_device *pdev)
if (ret < 0)
return -EINVAL;
- irq = platform_get_irq_byname(pdev, "fifo");
- if (irq < 0)
- return irq;
-
- ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_bms_vm_fifo_update_done_irq,
- IRQF_ONESHOT, "pm8916_vm_bms", bat);
- if (ret)
- return ret;
-
ret = regmap_bulk_read(bat->regmap, bat->reg + PM8916_PERPH_TYPE, &tmp, 2);
if (ret)
goto comm_error;
@@ -220,6 +211,15 @@ static int pm8916_bms_vm_battery_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Unable to get battery info\n");
+ irq = platform_get_irq_byname(pdev, "fifo");
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_bms_vm_fifo_update_done_irq,
+ IRQF_ONESHOT, "pm8916_vm_bms", bat);
+ if (ret)
+ return ret;
+
platform_set_drvdata(pdev, bat);
return 0;
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 09/11] power: supply: pm8916_lbc: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (7 preceding siblings ...)
2025-12-20 22:36 ` [PATCH 07/11] power: supply: pf1550: " Waqar Hameed
@ 2025-12-20 22:36 ` Waqar Hameed
2025-12-21 5:45 ` Nikita Travkin
2025-12-20 22:36 ` [PATCH 11/11] power: supply: sbs-battery: " Waqar Hameed
2025-12-20 22:36 ` [PATCH 10/11] power: supply: rt9455: " Waqar Hameed
10 siblings, 1 reply; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:36 UTC (permalink / raw)
To: Sebastian Reichel, Nikita Travkin; +Cc: kernel, linux-pm, linux-kernel
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: f8d7a3d21160 ("power: supply: Add driver for pm8916 lbc")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/pm8916_lbc.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/power/supply/pm8916_lbc.c b/drivers/power/supply/pm8916_lbc.c
index c74b75b1b2676..3ca717d84aade 100644
--- a/drivers/power/supply/pm8916_lbc.c
+++ b/drivers/power/supply/pm8916_lbc.c
@@ -274,15 +274,6 @@ static int pm8916_lbc_charger_probe(struct platform_device *pdev)
return dev_err_probe(dev, -EINVAL,
"Wrong amount of reg values: %d (4 expected)\n", len);
- irq = platform_get_irq_byname(pdev, "usb_vbus");
- if (irq < 0)
- return irq;
-
- ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_lbc_charger_state_changed_irq,
- IRQF_ONESHOT, "pm8916_lbc", chg);
- if (ret)
- return ret;
-
ret = device_property_read_u32_array(dev, "reg", chg->reg, len);
if (ret)
return ret;
@@ -332,6 +323,15 @@ static int pm8916_lbc_charger_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "Unable to get battery info\n");
+ irq = platform_get_irq_byname(pdev, "usb_vbus");
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_lbc_charger_state_changed_irq,
+ IRQF_ONESHOT, "pm8916_lbc", chg);
+ if (ret)
+ return ret;
+
chg->edev = devm_extcon_dev_allocate(dev, pm8916_lbc_charger_cable);
if (IS_ERR(chg->edev))
return PTR_ERR(chg->edev);
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 10/11] power: supply: rt9455: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (9 preceding siblings ...)
2025-12-20 22:36 ` [PATCH 11/11] power: supply: sbs-battery: " Waqar Hameed
@ 2025-12-20 22:36 ` Waqar Hameed
10 siblings, 0 replies; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:36 UTC (permalink / raw)
To: Sebastian Reichel, Krzysztof Kozlowski, Anda-Maria Nicolae
Cc: kernel, linux-pm, linux-kernel
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@axis.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
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 11/11] power: supply: sbs-battery: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
` (8 preceding siblings ...)
2025-12-20 22:36 ` [PATCH 09/11] power: supply: pm8916_lbc: " Waqar Hameed
@ 2025-12-20 22:36 ` Waqar Hameed
2026-01-05 3:16 ` Phil Reid
2025-12-20 22:36 ` [PATCH 10/11] power: supply: rt9455: " Waqar Hameed
10 siblings, 1 reply; 17+ messages in thread
From: Waqar Hameed @ 2025-12-20 22:36 UTC (permalink / raw)
To: Sebastian Reichel, Phil Reid
Cc: kernel, Sebastian Reichel, Phil Reid, linux-pm, linux-kernel
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. Keep the old behavior of
just printing a warning in case of any failures during the IRQ request
and finishing the probe successfully.
Fixes: d2cec82c2880 ("power: sbs-battery: Request threaded irq and fix dev callback cookie")
Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
---
drivers/power/supply/sbs-battery.c | 36 +++++++++++++++---------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c
index 943c82ee978f4..43c48196c1674 100644
--- a/drivers/power/supply/sbs-battery.c
+++ b/drivers/power/supply/sbs-battery.c
@@ -1174,24 +1174,6 @@ static int sbs_probe(struct i2c_client *client)
i2c_set_clientdata(client, chip);
- if (!chip->gpio_detect)
- goto skip_gpio;
-
- irq = gpiod_to_irq(chip->gpio_detect);
- if (irq <= 0) {
- dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
- goto skip_gpio;
- }
-
- rc = devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- dev_name(&client->dev), chip);
- if (rc) {
- dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
- goto skip_gpio;
- }
-
-skip_gpio:
/*
* Before we register, we might need to make sure we can actually talk
* to the battery.
@@ -1217,6 +1199,24 @@ static int sbs_probe(struct i2c_client *client)
return dev_err_probe(&client->dev, PTR_ERR(chip->power_supply),
"Failed to register power supply\n");
+ if (!chip->gpio_detect)
+ goto out;
+
+ irq = gpiod_to_irq(chip->gpio_detect);
+ if (irq <= 0) {
+ dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
+ goto out;
+ }
+
+ rc = devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ dev_name(&client->dev), chip);
+ if (rc) {
+ dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
+ goto out;
+ }
+
+out:
dev_info(&client->dev,
"%s: battery gas gauge device registered\n", client->name);
--
2.39.5
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 09/11] power: supply: pm8916_lbc: Fix use-after-free in power_supply_changed()
2025-12-20 22:36 ` [PATCH 09/11] power: supply: pm8916_lbc: " Waqar Hameed
@ 2025-12-21 5:45 ` Nikita Travkin
0 siblings, 0 replies; 17+ messages in thread
From: Nikita Travkin @ 2025-12-21 5:45 UTC (permalink / raw)
To: Waqar Hameed; +Cc: Sebastian Reichel, kernel, linux-pm, linux-kernel
Waqar Hameed писал(а) 21.12.2025 03:36:
> 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: f8d7a3d21160 ("power: supply: Add driver for pm8916 lbc")
> Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
> ---
> drivers/power/supply/pm8916_lbc.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/power/supply/pm8916_lbc.c b/drivers/power/supply/pm8916_lbc.c
> index c74b75b1b2676..3ca717d84aade 100644
> --- a/drivers/power/supply/pm8916_lbc.c
> +++ b/drivers/power/supply/pm8916_lbc.c
> @@ -274,15 +274,6 @@ static int pm8916_lbc_charger_probe(struct platform_device *pdev)
> return dev_err_probe(dev, -EINVAL,
> "Wrong amount of reg values: %d (4 expected)\n", len);
>
> - irq = platform_get_irq_byname(pdev, "usb_vbus");
> - if (irq < 0)
> - return irq;
> -
> - ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_lbc_charger_state_changed_irq,
> - IRQF_ONESHOT, "pm8916_lbc", chg);
> - if (ret)
> - return ret;
> -
> ret = device_property_read_u32_array(dev, "reg", chg->reg, len);
> if (ret)
> return ret;
> @@ -332,6 +323,15 @@ static int pm8916_lbc_charger_probe(struct platform_device *pdev)
> if (ret)
> return dev_err_probe(dev, ret, "Unable to get battery info\n");
>
> + irq = platform_get_irq_byname(pdev, "usb_vbus");
> + if (irq < 0)
> + return irq;
> +
> + ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_lbc_charger_state_changed_irq,
> + IRQF_ONESHOT, "pm8916_lbc", chg);
> + if (ret)
> + return ret;
> +
Thank you for looking at those drivers and fixing this!
As a small note, the interrupt handler also has a call to
extcon_set_state_sync(chg->edev,...) which is allocated right below.
I don't think this is actually a problem since it has a null check for
edev (unlike psy core) so I think this patch is fine as-is. However if
for some reason you'd have to respin this series, perhaps it would be
nice to move irq registration slightly lower, after extcon registration.
In any case,
Reviewed-by: Nikita Travkin <nikita@trvn.ru>
Nikita
> chg->edev = devm_extcon_dev_allocate(dev, pm8916_lbc_charger_cable);
> if (IS_ERR(chg->edev))
> return PTR_ERR(chg->edev);
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 08/11] power: supply: pm8916_bms_vm: Fix use-after-free in power_supply_changed()
2025-12-20 22:36 ` [PATCH 08/11] power: supply: pm8916_bms_vm: " Waqar Hameed
@ 2025-12-21 5:47 ` Nikita Travkin
0 siblings, 0 replies; 17+ messages in thread
From: Nikita Travkin @ 2025-12-21 5:47 UTC (permalink / raw)
To: Waqar Hameed; +Cc: Sebastian Reichel, kernel, linux-pm, linux-kernel
Waqar Hameed писал(а) 21.12.2025 03:36:
> 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: 098bce1838e0 ("power: supply: Add pm8916 VM-BMS support")
> Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
Reviewed-by: Nikita Travkin <nikita@trvn.ru>
Thanks for fixing this!
Nikita
> ---
> drivers/power/supply/pm8916_bms_vm.c | 18 +++++++++---------
> 1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/power/supply/pm8916_bms_vm.c b/drivers/power/supply/pm8916_bms_vm.c
> index 5120be086e6ff..de5d571c03e21 100644
> --- a/drivers/power/supply/pm8916_bms_vm.c
> +++ b/drivers/power/supply/pm8916_bms_vm.c
> @@ -167,15 +167,6 @@ static int pm8916_bms_vm_battery_probe(struct platform_device *pdev)
> if (ret < 0)
> return -EINVAL;
>
> - irq = platform_get_irq_byname(pdev, "fifo");
> - if (irq < 0)
> - return irq;
> -
> - ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_bms_vm_fifo_update_done_irq,
> - IRQF_ONESHOT, "pm8916_vm_bms", bat);
> - if (ret)
> - return ret;
> -
> ret = regmap_bulk_read(bat->regmap, bat->reg + PM8916_PERPH_TYPE, &tmp, 2);
> if (ret)
> goto comm_error;
> @@ -220,6 +211,15 @@ static int pm8916_bms_vm_battery_probe(struct platform_device *pdev)
> if (ret)
> return dev_err_probe(dev, ret, "Unable to get battery info\n");
>
> + irq = platform_get_irq_byname(pdev, "fifo");
> + if (irq < 0)
> + return irq;
> +
> + ret = devm_request_threaded_irq(dev, irq, NULL, pm8916_bms_vm_fifo_update_done_irq,
> + IRQF_ONESHOT, "pm8916_vm_bms", bat);
> + if (ret)
> + return ret;
> +
> platform_set_drvdata(pdev, bat);
>
> return 0;
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 01/11] power: supply: ab8500: Fix use-after-free in power_supply_changed()
2025-12-20 22:35 ` [PATCH 01/11] power: supply: ab8500: " Waqar Hameed
@ 2025-12-22 22:35 ` Linus Walleij
0 siblings, 0 replies; 17+ messages in thread
From: Linus Walleij @ 2025-12-22 22:35 UTC (permalink / raw)
To: Waqar Hameed; +Cc: Sebastian Reichel, kernel, linux-pm, linux-kernel
Hi Waqar,
thanks a lot for looking into this!
On Sat, Dec 20, 2025 at 11:36 PM Waqar Hameed <waqar.hameed@axis.com> wrote:
> 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()`.
>
> Commit 1c1f13a006ed ("power: supply: ab8500: Move to componentized
> binding") introduced this issue during a refactorization. Fix this racy
> use-after-free by making sure the IRQ is requested _after_ the
> registration of the `power_supply` handle.
>
> Fixes: 1c1f13a006ed ("power: supply: ab8500: Move to componentized binding")
> Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
Hats off, it's a clean and precise fix.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 11/11] power: supply: sbs-battery: Fix use-after-free in power_supply_changed()
2025-12-20 22:36 ` [PATCH 11/11] power: supply: sbs-battery: " Waqar Hameed
@ 2026-01-05 3:16 ` Phil Reid
0 siblings, 0 replies; 17+ messages in thread
From: Phil Reid @ 2026-01-05 3:16 UTC (permalink / raw)
To: Waqar Hameed, Sebastian Reichel; +Cc: kernel, linux-pm, linux-kernel
On 21/12/2025 06:36, Waqar Hameed wrote:
> 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. Keep the old behavior of
> just printing a warning in case of any failures during the IRQ request
> and finishing the probe successfully.
>
> Fixes: d2cec82c2880 ("power: sbs-battery: Request threaded irq and fix dev callback cookie")
> Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
Reviewed-by: Phil Reid <preid@electromag.com.au>
> ---
> drivers/power/supply/sbs-battery.c | 36 +++++++++++++++---------------
> 1 file changed, 18 insertions(+), 18 deletions(-)
>
> diff --git a/drivers/power/supply/sbs-battery.c b/drivers/power/supply/sbs-battery.c
> index 943c82ee978f4..43c48196c1674 100644
> --- a/drivers/power/supply/sbs-battery.c
> +++ b/drivers/power/supply/sbs-battery.c
> @@ -1174,24 +1174,6 @@ static int sbs_probe(struct i2c_client *client)
>
> i2c_set_clientdata(client, chip);
>
> - if (!chip->gpio_detect)
> - goto skip_gpio;
> -
> - irq = gpiod_to_irq(chip->gpio_detect);
> - if (irq <= 0) {
> - dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
> - goto skip_gpio;
> - }
> -
> - rc = devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq,
> - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> - dev_name(&client->dev), chip);
> - if (rc) {
> - dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
> - goto skip_gpio;
> - }
> -
> -skip_gpio:
> /*
> * Before we register, we might need to make sure we can actually talk
> * to the battery.
> @@ -1217,6 +1199,24 @@ static int sbs_probe(struct i2c_client *client)
> return dev_err_probe(&client->dev, PTR_ERR(chip->power_supply),
> "Failed to register power supply\n");
>
> + if (!chip->gpio_detect)
> + goto out;
> +
> + irq = gpiod_to_irq(chip->gpio_detect);
> + if (irq <= 0) {
> + dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
> + goto out;
> + }
> +
> + rc = devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq,
> + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
> + dev_name(&client->dev), chip);
> + if (rc) {
> + dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
> + goto out;
> + }
> +
> +out:
> dev_info(&client->dev,
> "%s: battery gas gauge device registered\n", client->name);
>
--
Regards
Phil Reid
ElectroMagnetic Imaging Technology Pty Ltd
Development of Geophysical Instrumentation & Software
www.electromag.com.au
23 Junction Parade, Midland WA 6056, AUSTRALIA
Ph: +61 8 9250 8100
Fax: +61 8 9250 7100
Email: preid@electromag.com.au
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 07/11] power: supply: pf1550: Fix use-after-free in power_supply_changed()
2025-12-20 22:36 ` [PATCH 07/11] power: supply: pf1550: " Waqar Hameed
@ 2026-01-06 2:59 ` Samuel Kayode
0 siblings, 0 replies; 17+ messages in thread
From: Samuel Kayode @ 2026-01-06 2:59 UTC (permalink / raw)
To: Waqar Hameed
Cc: Sebastian Reichel, Frank Li, Lee Jones, kernel, imx, linux-pm,
linux-kernel
On Sat, Dec 20, 2025 at 11:36:01PM +0100, Waqar Hameed wrote:
> 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: 4b6b6433a97d ("power: supply: pf1550: add battery charger support")
> Signed-off-by: Waqar Hameed <waqar.hameed@axis.com>
Reviewed-by: Samuel Kayode <samkay014@gmail.com>
Thank you!
Sam
> ---
> drivers/power/supply/pf1550-charger.c | 32 +++++++++++++--------------
> 1 file changed, 16 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/power/supply/pf1550-charger.c b/drivers/power/supply/pf1550-charger.c
> index 98f1ee8eca3bc..a457862ef4610 100644
> --- a/drivers/power/supply/pf1550-charger.c
> +++ b/drivers/power/supply/pf1550-charger.c
> @@ -584,22 +584,6 @@ static int pf1550_charger_probe(struct platform_device *pdev)
> return dev_err_probe(chg->dev, ret,
> "failed to add battery sense work\n");
>
> - for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) {
> - irq = platform_get_irq(pdev, i);
> - if (irq < 0)
> - return irq;
> -
> - chg->virqs[i] = irq;
> -
> - ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
> - pf1550_charger_irq_handler,
> - IRQF_NO_SUSPEND,
> - "pf1550-charger", chg);
> - if (ret)
> - return dev_err_probe(&pdev->dev, ret,
> - "failed irq request\n");
> - }
> -
> psy_cfg.drv_data = chg;
>
> chg->charger = devm_power_supply_register(&pdev->dev,
> @@ -616,6 +600,22 @@ static int pf1550_charger_probe(struct platform_device *pdev)
> return dev_err_probe(&pdev->dev, PTR_ERR(chg->battery),
> "failed: power supply register\n");
>
> + for (i = 0; i < PF1550_CHARGER_IRQ_NR; i++) {
> + irq = platform_get_irq(pdev, i);
> + if (irq < 0)
> + return irq;
> +
> + chg->virqs[i] = irq;
> +
> + ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
> + pf1550_charger_irq_handler,
> + IRQF_NO_SUSPEND,
> + "pf1550-charger", chg);
> + if (ret)
> + return dev_err_probe(&pdev->dev, ret,
> + "failed irq request\n");
> + }
> +
> pf1550_dt_parse_dev_info(chg);
>
> return pf1550_reg_init(chg);
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-01-06 2:59 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-20 22:35 [PATCH 00/11] power: supply: Fix use-after-free in power_supply_changed() Waqar Hameed
2025-12-20 22:35 ` [PATCH 01/11] power: supply: ab8500: " Waqar Hameed
2025-12-22 22:35 ` Linus Walleij
2025-12-20 22:35 ` [PATCH 02/11] power: supply: act8945a: " Waqar Hameed
2025-12-20 22:35 ` [PATCH 03/11] power: supply: bq256xx: " Waqar Hameed
2025-12-20 22:35 ` [PATCH 04/11] power: supply: bq25980: " Waqar Hameed
2025-12-20 22:36 ` [PATCH 06/11] power: supply: goldfish: " Waqar Hameed
2025-12-20 22:36 ` [PATCH 05/11] power: supply: cpcap-battery: " Waqar Hameed
2025-12-20 22:36 ` [PATCH 08/11] power: supply: pm8916_bms_vm: " Waqar Hameed
2025-12-21 5:47 ` Nikita Travkin
2025-12-20 22:36 ` [PATCH 07/11] power: supply: pf1550: " Waqar Hameed
2026-01-06 2:59 ` Samuel Kayode
2025-12-20 22:36 ` [PATCH 09/11] power: supply: pm8916_lbc: " Waqar Hameed
2025-12-21 5:45 ` Nikita Travkin
2025-12-20 22:36 ` [PATCH 11/11] power: supply: sbs-battery: " Waqar Hameed
2026-01-05 3:16 ` Phil Reid
2025-12-20 22:36 ` [PATCH 10/11] power: supply: rt9455: " Waqar Hameed
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).