FAILED: patch "[PATCH] power: supply: lp8788-charger: fix use-after-free on remove" failed to apply to 6.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 831c29a12d560f8a3225f43050b3fbb5dfd79c66
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090352-shoptalk-president-e8c6@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 831c29a12d560f8a3225f43050b3fbb5dfd79c66 Mon Sep 17 00:00:00 2001
From: Fan Wu <[email protected]>
Date: Sun, 2 Aug 2026 03:54:42 +0000
Subject: [PATCH] power: supply: lp8788-charger: fix use-after-free on remove
lp8788_charger_remove() flushes charger_work before unregistering the IRQs. An IRQ thread can queue charger_work after flush_work() has returned. The work can then run after devres frees pchg and dereference it in lp8788_charger_event().
Unregister the IRQs first. free_irq() waits for any running threaded handler, so no handler can queue more work afterwards. Then use cancel_work_sync() to cancel pending work or wait for running work to finish.
This issue was found by an in-house static analysis tool.
drivers/power/supply/lp8788-charger.c +1 -1
@@ -710,8 +710,8 @@ static void lp8788_charger_remove(struct platform_device *pdev) {struct lp8788_charger *pchg =platform_get_drvdata (pdev); -flush_work (&pchg->charger_work);lp8788_irq_unregister (pdev, pchg); +cancel_work_sync (&pchg->charger_work); }static struct platform_driver lp8788_charger_driver = {
Sasha Levin
maintainerPATCH 1/3 power: supply: lp8788-charger: Convert to platform remove callback returning void
From: Uwe Kleine-König <[email protected]>
[ Upstream commit 7810ba3c5110ce66652ec6bd2abb92da5d726c3b ]
The .remove() callback for a platform driver returns an int which makes many driver authors wrongly assume it's possible to do error handling by returning an error code. However the value returned is ignored (apart from emitting a warning) and this typically results in resource leaks. To improve here there is a quest to make the remove callback return void. In the first step of this quest all drivers are converted to .remove_new() which already returns void. Eventually after all drivers are converted, .remove_new() is renamed to .remove().
Trivially convert this driver from always returning zero in the remove callback to the void returning variant.
Stable-dep-of: 831c29a12d56 ("power: supply: lp8788-charger: fix use-after-free on remove")
--- drivers/power/supply/lp8788-charger.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/power/supply/lp8788-charger.c +2 -4
@@ -715,20 +715,18 @@ static int lp8788_charger_probe(struct platform_device *pdev)return 0 ; } -static int lp8788_charger_remove (struct platform_device *pdev) +static void lp8788_charger_remove (struct platform_device *pdev) {struct lp8788_charger *pchg =platform_get_drvdata (pdev);flush_work (&pchg->charger_work);lp8788_irq_unregister (pdev, pchg);lp8788_psy_unregister (pchg); - -return 0 ; }static struct platform_driver lp8788_charger_driver = { .probe = lp8788_charger_probe, - .remove = lp8788_charger_remove, + .remove_new = lp8788_charger_remove, .driver = { .name =LP8788_DEV_CHARGER , },
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 power: supply: lp8788: Use devm_power_supply_register() helper
From: Andrew Davis <[email protected]>
[ Upstream commit 2abb571143c39f581df9951d263948726db42d86 ]
Use the device lifecycle managed register function. This helps prevent mistakes like unregistering out of order in cleanup functions and forgetting to unregister on error paths.
Stable-dep-of: 831c29a12d56 ("power: supply: lp8788-charger: fix use-after-free on remove")
--- drivers/power/supply/lp8788-charger.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-)
drivers/power/supply/lp8788-charger.c +6 -15
@@ -406,12 +406,6 @@ static const struct power_supply_desc lp8788_psy_battery_desc = { .get_property = lp8788_battery_get_property, }; -static void lp8788_psy_unregister (struct lp8788_charger *pchg) -{ -power_supply_unregister (pchg->battery); -power_supply_unregister (pchg->charger); -} -static void lp8788_charger_event (struct work_struct *work) { struct lp8788_charger *pchg =
@@ -667,18 +661,16 @@ static int lp8788_psy_register(struct platform_device *pdev, charger_cfg.supplied_to = battery_supplied_to; charger_cfg.num_supplicants =ARRAY_SIZE (battery_supplied_to); - pchg->charger =power_supply_register (&pdev->dev, - &lp8788_psy_charger_desc, - &charger_cfg); + pchg->charger =devm_power_supply_register (&pdev->dev, + &lp8788_psy_charger_desc, + &charger_cfg);if (IS_ERR (pchg->charger))return -EPERM ; - pchg->battery =power_supply_register (&pdev->dev, - &lp8788_psy_battery_desc,NULL ); -if (IS_ERR (pchg->battery)) { -power_supply_unregister (pchg->charger); + pchg->battery =devm_power_supply_register (&pdev->dev, + &lp8788_psy_battery_desc,NULL ); +if (IS_ERR (pchg->battery))return -EPERM ; - }return 0 ; }
@@ -721,7 +713,6 @@ static void lp8788_charger_remove(struct platform_device *pdev)flush_work (&pchg->charger_work);lp8788_irq_unregister (pdev, pchg); -lp8788_psy_unregister (pchg); }static struct platform_driver lp8788_charger_driver = {
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 power: supply: lp8788-charger: fix use-after-free on remove
In reply to Sasha LevinFrom: Fan Wu <[email protected]>
[ Upstream commit 831c29a12d560f8a3225f43050b3fbb5dfd79c66 ]
lp8788_charger_remove() flushes charger_work before unregistering the IRQs. An IRQ thread can queue charger_work after flush_work() has returned. The work can then run after devres frees pchg and dereference it in lp8788_charger_event().
Unregister the IRQs first. free_irq() waits for any running threaded handler, so no handler can queue more work afterwards. Then use cancel_work_sync() to cancel pending work or wait for running work to finish.
This issue was found by an in-house static analysis tool.
--- drivers/power/supply/lp8788-charger.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/supply/lp8788-charger.c +1 -1
@@ -711,8 +711,8 @@ static void lp8788_charger_remove(struct platform_device *pdev) {struct lp8788_charger *pchg =platform_get_drvdata (pdev); -flush_work (&pchg->charger_work);lp8788_irq_unregister (pdev, pchg); +cancel_work_sync (&pchg->charger_work); }static struct platform_driver lp8788_charger_driver = {
Signature · 1 line
2.53.0