Re: [PATCH] power: supply: ucs1002: fix use-after-free on remove
Lucas Stach <[email protected]> Mon, 03 Aug 2026 11:17:27 +0200
| Newsgroups | org.kernel.vger.linux-pm,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
Am Sonntag, dem 02.08.2026 um 05:12 +0000 schrieb Fan Wu:
> ucs1002 has no remove callback, so unbind runs entirely through devm.
> The alert IRQ handler queues the health_poll delayed work, and the work
> reschedules itself while the chip reports a bad-health condition. devm
> frees the alert IRQ, which only synchronizes the handler; it does not
> cancel the delayed work, which can then run after devm frees the driver
> data and dereference it.
>=20
> Register health_poll with devm_delayed_work_autocancel() before the
> alert IRQ is requested. devm then frees the IRQ before cancelling the
> work, so the handler can no longer queue it and the work is cancelled
> before the driver data is freed.
>=20
> This issue was found by an in-house static analysis tool.
>=20
> Fixes: 81196e2e57fc ("power: supply: ucs1002: fix some health status issu=
es")
> Cc: [email protected]
> Assisted-by: Codex:gpt-5.6
> Signed-off-by: Fan Wu <[email protected]>
Reviewed-by: Lucas Stach <[email protected]>
> ---
> drivers/power/supply/ucs1002_power.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>=20
> diff --git a/drivers/power/supply/ucs1002_power.c b/drivers/power/supply/=
ucs1002_power.c
> index 3f44cc9..ca58c21 100644
> --- a/drivers/power/supply/ucs1002_power.c
> +++ b/drivers/power/supply/ucs1002_power.c
> @@ -11,6 +11,7 @@
> #include <linux/kernel.h>
> #include <linux/kthread.h>
> #include <linux/device.h>
> +#include <linux/devm-helpers.h>
> #include <linux/module.h>
> #include <linux/of.h>
> #include <linux/of_irq.h>
> @@ -640,7 +641,10 @@ static int ucs1002_probe(struct i2c_client *client)
> }
> =20
> info->health =3D POWER_SUPPLY_HEALTH_GOOD;
> - INIT_DELAYED_WORK(&info->health_poll, ucs1002_health_poll);
> + ret =3D devm_delayed_work_autocancel(dev, &info->health_poll,
> + ucs1002_health_poll);
> + if (ret)
> + return ret;
> =20
> if (irq_a_det > 0) {
> ret =3D devm_request_threaded_irq(dev, irq_a_det, NULL,