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,