CVE-2026-89468: power: supply: lp8788-charger: fix use-after-free on remove
In the Linux kernel, the following vulnerability has been resolved:
power: supply: lp8788-charger: fix use-after-free on remove
lp8788chargerremove() flushes chargerwork before unregistering the IRQs. An IRQ thread can queue chargerwork after flushwork() has returned. The work can then run after devres frees pchg and dereference it in lp8788chargerevent().
Unregister the IRQs first. freeirq() waits for any running threaded handler, so no handler can queue more work afterwards. Then use cancelworksync() to cancel pending work or wait for running work to finish.
This issue was found by an in-house static analysis tool.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Configuration
In lp8788_charger_remove(), cancel pending charger_work with cancel_work_sync() (or flush charger_work) before unregistering IRQs. Then unregister the IRQs first; use free_irq() (which waits for any running threaded handler) so no IRQ handler can queue charger_work after devres frees pchg. This prevents the use-after-free where a charger_work queued from an IRQ thread can run after flush_work() has returned.
Linux kernel (lp8788 charger driver) IRQ removal order / threaded work cancellation = Register IRQs -> on remove: cancel_work_sync() and flush_work() before unregistering IRQs; then unregister IRQs and free_irq()
Event History
Frequently Asked Questions
Which systems are exposed to this issue?
Systems using the Linux kernel lp8788 charger driver are exposed during removal of the charger device if its threaded IRQ handler can run concurrently with teardown.
What condition is required to trigger the use-after-free?
An IRQ thread must queue charger_work after the remove path has flushed the work but before the IRQs are unregistered. The queued work can then run after devres has freed the driver state.
What is the required teardown order to prevent the race?
The IRQs must be unregistered before pending charger work is handled. After free_irq() prevents further threaded handlers from queuing work, cancel_work_sync() should cancel pending work or wait for running work to complete.