Re: [PATCH] power: supply: qcom_battmgr: fix use-after-free of battmgr on remove
Sebastian Reichel <[email protected]> Fri, 31 Jul 2026 23:43:30 +0200
| Newsgroups | org.kernel.vger.linux-pm,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <am0V6zvEDsNd8J2L@venus> |
Hi,
On Fri, Jul 31, 2026 at 02:20:06AM +0000, Fan Wu wrote:
> qcom_battmgr_pdr_notify() queues enable_work when the PMIC GLINK service
> comes up. The worker recovers battmgr through container_of() and issues a
> firmware request.
>
> The driver has no remove callback, so a pending or running enable_work can
> access battmgr after devres frees it. The PMIC GLINK client stays on the
> client list until its devres release action, so a PDR notification can
> also queue the work while remove is running.
>
> Add a remove callback that disables and drains enable_work before devres
> release. Unlike cancel_work_sync(), disable_work_sync() also blocks a later
> PDR notification from queueing the work. Store battmgr with
> auxiliary_set_drvdata() in probe so remove can retrieve it.
>
> This issue was found by an in-house static analysis tool.
>
> Fixes: 29e8142b5623 ("power: supply: Introduce Qualcomm PMIC GLINK power supply")
> Cc: [email protected] # v6.10+
> Assisted-by: Codex:gpt-5.6
> Signed-off-by: Fan Wu <[email protected]>
> ---
Your patch leaves a race condition. A notification might arrive
directly after disable_work_sync resulting in scheduling new work
from the notify function.
Considering the driver is fully converted to device managed
resources, it is better to replace INIT_WORK with
devm_work_autocancel() anyways. Just put it to the right location in
the probe function (directly before devm_pmic_glink_client_alloc())
and things should work correctly.
Greetings,
-- Sebastian
> drivers/power/supply/qcom_battmgr.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/drivers/power/supply/qcom_battmgr.c b/drivers/power/supply/qcom_battmgr.c
> index 490137a23d..f8c3efd2c9 100644
> --- a/drivers/power/supply/qcom_battmgr.c
> +++ b/drivers/power/supply/qcom_battmgr.c
> @@ -1638,6 +1638,8 @@ static int qcom_battmgr_probe(struct auxiliary_device *adev,
> if (!battmgr)
> return -ENOMEM;
>
> + auxiliary_set_drvdata(adev, battmgr);
> +
> battmgr->dev = dev;
>
> psy_cfg.drv_data = battmgr;
> @@ -1729,9 +1731,17 @@ static const struct auxiliary_device_id qcom_battmgr_id_table[] = {
> };
> MODULE_DEVICE_TABLE(auxiliary, qcom_battmgr_id_table);
>
> +static void qcom_battmgr_remove(struct auxiliary_device *adev)
> +{
> + struct qcom_battmgr *battmgr = auxiliary_get_drvdata(adev);
> +
> + disable_work_sync(&battmgr->enable_work);
> +}
> +
> static struct auxiliary_driver qcom_battmgr_driver = {
> .name = "pmic_glink_power_supply",
> .probe = qcom_battmgr_probe,
> + .remove = qcom_battmgr_remove,
> .id_table = qcom_battmgr_id_table,
> };
>
> --
> 2.34.1
>
signature.asc
(application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE72YNB0Y/i3JqeVQT2O7X88g7+poFAmptFvoACgkQ2O7X88g7 +po9Zg/9HZRLQDoVCsq29L8pz8bTGzIjhtfYe8QnzuDmJ78gFWpyVmZzRol4nvh4 U0daNKa3FzMQ17yY7iLXrtiucksu5tbklLpiHnhg3nY4C5gpjL2lfjgWHKgpBX6C 9vrdBH6Wjr4odzqs7HSrJBg65XNYprf/UJoi7McPjH7anXU43iVzaADb0D9mIEkJ zrPUI2i7kj1qZzZeWXB20P0rndl/foauw2j3lrXlrIwsys7dz+BN5p8MgSggWlPO MRezYVhZt5HN5LQZFpZHzAMZOuofeoDsjsAq/73GKb87CLAKcwHBUO+BzDdFPrK7 2T37eBdHT9/5FA/tMvMkWKttPqa/7bbYQ+HPVRnAFZBYg9jpWZrhbmSBvtJmvxBH Ly5pZNnd7Gqsp7BVYz/4/NDEp2hw63Rpss6vWZ849234h3xZ+doeAvcLG5qlf4la utjpUUARbtS+uFsHfhAIp1GGcGgnqZ3waVSC3hj3oLFGTGLMKXw8S0eW+WArnEzj 3cRmAPZ29yNAfs62VM3C7QMIK34FIlhw9RKHtj1Ae/1aW/InEc0NUOBCIYyBIkte PIug/K5oN1eWBKgEscWr5TbZvy5GtU7MzY+QsGQrssPkMEFEq/kLn1sZA4RliqrQ DUCogDHUaNfK6c12UmaKSXA0ukFG/HtQmn0qt1Tm+z8SgBIWogs= =RfPG -----END PGP SIGNATURE-----