From: 徐晗翔 <xuhx@hust.edu.cn>
To: sre@kernel.org
Cc: linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: power: supply: bq24190: IRQ handler can call power_supply_changed after the psy is unregistered
Date: Tue, 10 Nov 2026 21:34:27 +0800 (GMT+08:00) [thread overview]
Message-ID: <53a5f0c4.22b5a.1a1c5aacb18.Coremail.xuhx@hust.edu.cn> (raw)
In-Reply-To: <2026102727-data-sequel-ce41@gregkh>
bq24190_remove() unregisters the battery and charger power_supplies
before pm_runtime_disable(); the IRQ is requested with devm and is
therefore freed only after remove returns. A threaded IRQ handler that
is already running, or one that runs in the window between the two
unregisters and pm_runtime_disable(), calls bq24190_check_status() ->
power_supply_changed() on a psy that has already been unregistered (and
may be freed). This is a driver remove-order bug; the window is
narrower than bq25890 but real.
The detailed description:
* Test environment / affected version
Linux 7.3.0 source tree (unmodified kernel.org 7.3), x86_64. This is
a source-level report. I did not run it on bq24190 hardware: the
KASAN build used for my core tests does not enable
CONFIG_CHARGER_BQ24190 and has no I2C bq24190 device. No reproducer
is attached. Line numbers are from 7.3.
* Mechanism
Probe:
:2121 power_supply_register(bdi->battery, ...)
:2133 power_supply_register(bdi->charger, ...)
:2160 devm_request_threaded_irq(..., bq24190_irq_handler_thread, ...)
Both power_supplies are non-devm. The IRQ is devm, so it is released
by devres after bq24190_remove() returns, not before.
bq24190_remove() (:2189-2206):
:2200 power_supply_unregister(bdi->battery);
:2201 power_supply_unregister(bdi->charger);
:2202-2204 pm_runtime_put...
:2205 pm_runtime_disable...
The threaded handler (:1834-1850) calls bq24190_check_status()
(:1824-1829), which calls power_supply_changed(bdi->charger/battery).
Window A: an IRQ is delivered after :2201 and before :2205; the
handler runs while both psy are already unregistered. Window B: a
handler is already running when :2200/:2201 execute; it can reach
power_supply_changed() after unregister. After :2205,
pm_runtime_disable() makes new IRQ handling less likely to reach the
callback, so I do not claim arbitrary post-remove IRQs; the
deterministic window is :2201-:2205, plus the in-flight handler.
* Concrete corruption / impact
power_supply_changed() dereferences psy->changed_lock; if the psy has
been freed, this is a slab-use-after-free and can corrupt the
workqueue or crash. If a consumer reference keeps the psy alive, the
call is a use-after-unregister and can reach the freed LED triggers
described in the core 5B report on a 7.3 kernel without the
9f7f7a859451 get/set guard. I have not demonstrated privilege
escalation, and I have not run this on hardware.
* Trigger model
bq24190 with a charger interrupt (AC plug/unplug, fault, or charger
status change) concurrent with unbind/remove. The window is narrow
(between the two unregisters and pm_runtime_disable, or an in-flight
handler), so it is a race rather than a deterministic sequence.
Unbinding requires root; a physical charger event is the natural
trigger. No generic unprivileged userspace interface.
* Reproducer / results
No reproducer attached. This is a source-level report; I can test a
proposed fix if bq24190 hardware is available. The relevant call
chain is fully visible in 7.3 at the line numbers above.
* Suggested direction
Disable the IRQ and wait for an in-flight handler before unregistering
the power_supplies: call disable_irq()/free_irq() (or an explicit
disable_irq + synchronize_irq) before :2200, and move
pm_runtime_disable() before the unregisters. Alternatively have the
handler check a "removed" flag set under a lock before
power_supply_changed(). Report-first, no patch attached; happy to
test a proposal.
Please keep me in Cc; I am not subscribed to the lists.
Regards,
Hanxiang Xu
xuhx@hust.edu.cn
prev parent reply other threads:[~2026-11-10 13:34 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-27 12:35 usb: devio: usbdev_release() has no barrier against an in-flight async_completed() callback (use-after-free window on struct usb_dev_state)gregkh@linuxfoundation.org 徐晗翔
2026-10-27 14:12 ` Greg KH
2026-11-03 11:21 ` mm/slub: has_pcs_used() reads remote per-CPU sheaf state from flush_all_cpus_locked() without synchronization (data race; KCSAN blind spot: slub.o is uninstrumented) 徐晗翔
2026-11-04 9:41 ` Qing Wang
2026-11-04 10:07 ` Qing Wang
2026-11-03 11:30 ` futex/hrtimer: hrtimer_sleeper::task is read unsynchronized in 16 places on v7.3 -- the accessor series that fixes this is not in 7.3; please make sure it reaches the affected trees (backport nudge + stock-kernel KCSAN evidence) 徐晗翔
2026-11-03 11:48 ` cgroup: fork vs cgroup.procs write race in favordynmods mode -- v7.3 is affected; please make sure bf6fbf46b5ff reaches the stable trees (repro incl. uninstrumented natural hit) 徐晗翔
2026-11-03 14:51 ` Sasha Levin
2026-11-03 11:57 ` net: rtnetlink: rtnl_link_unregister() vs in-flight RTM_GETLINK dump readers -- v7.3 lacks the synchronize_rcu() fix (Fixes: 6b57ff21a310 family); A/B reproduction on stock 7.3 徐晗翔
2026-11-03 15:49 ` Eric Dumazet
2026-11-04 15:03 ` Sasha Levin
2026-11-03 12:07 ` wifi: wilc1000: SDIO/SPI remove destroys the srcu_struct before wiphy_unregister() -- late cfg80211 callbacks write through dangling srcu state (unfixed upstream; controlled + natural Oops) 徐晗翔
2026-11-03 12:10 ` gpio: gpiolib: final put of the gpio_device happens inside the SRCU read critical section on the setup-failure path -- deterministic use-after-free read at guard release (unfixed upstream) 徐晗翔
2026-11-05 8:52 ` Linus Walleij
2026-11-04 12:54 ` soc: qcom: pmic_glink_altmode: fix use-after-free on unbind (no cancel_work_sync for port work and enable_work) 徐晗翔
2026-11-04 13:04 ` Greg KH
2026-11-04 12:57 ` usb: typec: anx7411: unregister partner/altmodes before stopping the IRQ work -- use-after-free, double unregister, orphan partner on remove 徐晗翔
2026-11-04 13:28 ` Greg KH
2026-11-04 12:58 ` usb: typec: ucsi: deadlock on cros_ec unbind -- connector lock held across cancel_delayed_work_sync vs the mode-selection work's unbounded trylock polling 徐晗翔
2026-11-04 13:00 ` usb: typec: stusb160x/rt1719/hd3ss3220: IRQ thread vs remove -- double unregister / use-after-free on the partner and port 徐晗翔
2026-11-04 13:01 ` usb: typec: ucsi: displayport: data race on dp->header/ vdo_data/vdo_size -- work reads them unlocked while writers hold con->lock (VDM mismatch) 徐晗翔
2026-11-04 13:02 ` usb: typec: class: three lifetime/locking gaps around the mux/switch handles and mode_selection (drvdata UAF after provider unbind; no concurrent protocol for set/put; unlocked state_update vs delete) 徐晗翔
2026-11-10 12:56 ` driver core: uevent: netns teardown frees uevent_sock while a tagged uevent is still being broadcast (UAF) 徐晗翔
2026-11-10 13:00 ` 徐晗翔
2026-11-10 13:05 ` ACPI: CPPC: per-CPU cpc_desc is freed on processor unbind without clearing the published pointer, causing UAF in cpufreq accessors 徐晗翔
2026-11-10 13:07 ` ACPI: CPPC: shared PCC subspace data can be freed while another CPU probes, reads, or tears it down 徐晗翔
2026-11-10 14:47 ` Christian Loehle
2026-11-10 13:11 ` ACPI: ACPICA: Reset can delete an event semaphore while another thread is blocked in Wait 徐晗翔
2026-11-10 13:14 ` power: supply: bq25890: pump-express work can call power_supply_changed after the psy is unregistered 徐晗翔
2026-11-10 13:17 ` power: supply: core: get/set property callbacks can run after unregister and read freed driver data 徐晗翔
2026-11-10 13:18 ` power: supply: core: system-battery enumeration can return an unregistered battery 徐晗翔
2026-11-10 13:21 ` power: supply: core: changed work can run after unregister and use freed LED triggers 徐晗翔
2026-11-10 13:23 ` power: supply: bq24190: IRQ handler can call power_supply_changed after the psy is unregistered 徐晗翔
2026-11-10 13:34 ` 徐晗翔 [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53a5f0c4.22b5a.1a1c5aacb18.Coremail.xuhx@hust.edu.cn \
--to=xuhx@hust.edu.cn \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=sre@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®