linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [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).