{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2026-89472","assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","state":"PUBLISHED","assignerShortName":"Linux","dateReserved":"2026-09-11T19:38:34.710Z","datePublished":"2026-09-11T19:43:30.536Z","dateUpdated":"2026-09-13T06:29:42.907Z"},"containers":{"cna":{"providerMetadata":{"orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","shortName":"Linux","dateUpdated":"2026-09-13T06:29:42.907Z"},"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\npower: supply: charger-manager: register regulators before exposing sysfs\n\ncharger_manager_remove() and the err_reg_extcon probe error path free each\ncharger regulator with regulator_put() before tearing down the power_supply\nsysfs entries (power_supply_unregister()). charger_manager_remove() also\ncalls try_charger_enable(cm, false) after the regulator_put() loop. A\nconcurrent write to a charger's externally_control sysfs attribute that\nlands between regulator_put() and power_supply_unregister() can run\ncharger_externally_control_store() and call try_charger_enable(), which,\nwhen charging is enabled, dereferences the already-freed consumer handle.\nWhen charging is enabled, try_charger_enable(cm, false) in .remove() also\ndereferences the freed handles directly. Both leave use-after-free windows.\nSymmetrically, probe registers the sysfs entries (power_supply_register)\nbefore acquiring the regulators (regulator_get, inside\ncharger_manager_register_extcon), so userspace can reach externally_control\nbefore the regulators are available.\n\nSplit charger_manager_register_extcon() on the sync/async boundary:\ncharger_manager_get_regulators() (regulator_get only, no async producer)\nnow runs before power_supply_register() so sysfs is not live before\nregulators are available, and charger_manager_register_extcon() keeps only\nthe extcon notifier/work setup, still after power_supply_register() so a\npower_supply_register() failure cannot reach extcon setup. This keeps the\nsysfs setup/teardown ordering symmetric without introducing an asynchronous\nproducer on the earlier probe-error path.\n\nMove power_supply_unregister() and try_charger_enable(cm, false) ahead of\nthe regulator_put() loop on both teardown paths, and adjust err_reg_extcon\n(power_supply_unregister() then fall through err_regulator for\nregulator_put(); get_regulators self-rolls back on its own failure).\n\nThis does not address the separate extcon-notifier-driven deref of the same\nhandles, which needs its own synchronization design.\n\nFound by an in-house static analysis tool."}],"metrics":[{"cvssV3_1":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH"},"scenarios":[{"lang":"en","value":"AV:L - The UAF is reached via local sysfs under /sys/class/power_supply/*/charger.N/{state,externally_control} and via charger_manager_remove()/probe unwind on the charger-manager platform device; this power-supply driver has no network, Bluetooth, or remote packet path into try_charger_enable() or the sysfs handlers.\nAC:L - An attacker can hammer the live sysfs attributes while teardown or probe unwind runs, controlling the sysfs side of the race; charger_manager_remove() also deterministically calls try_charger_enable() on already-freed regulator consumers when charging is enabled, with no attacker-uncontrollable memory layout required.\nPR:L - charger.N/state is mode 0444 and charger_state_show() calls regulator_is_enabled() on the consumer, so an unprivileged local user (including apps on charger-manager phones/embedded devices) can hit the UAF during the teardown or probe window; per driver-removal UAF precedent this is PR:L even though sysfs unbind itself is privileged.\nUI:N - The attacker performs their own sysfs reads or writes against the charger-manager power_supply attributes and can race driver unbind or probe; no separate victim action such as mounting a filesystem or confirming a prompt is required.\nS:U - The dangling struct regulator is kernel heap used by the same host kernel; this is a standard in-kernel use-after-free/privilege-escalation within one security authority, not a VM escape, IOMMU bypass, or sandbox breakout.\nC:H - regulator_put() kfree()s the struct regulator while charger_state_show() and try_charger_enable() still dereference the consumer; this heap UAF lets a reused object be read through regulator_is_enabled() and related helpers, enabling arbitrary kernel information disclosure.\nI:H - The same dangling consumer is passed to regulator_enable(), regulator_disable(), and regulator_force_disable() from try_charger_enable() and charger_externally_control_store(), so a sprayed heap object can turn the UAF into arbitrary writes and control-flow hijack.\nA:H - Use of the freed or still-NULL regulator consumer oopses or panics the kernel in regulator_is_enabled()/enable()/disable(), and the UAF crashes even when it is not fully converted into a read/write primitive."}]}],"affected":[{"product":"Linux","vendor":"Linux","defaultStatus":"unaffected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/power/supply/charger-manager.c"],"versions":[{"version":"3950c7865cd7c963982a2c94457182b96732f4c9","lessThan":"af3ce383ba0d0d48957a22ac7058ff5698775898","status":"affected","versionType":"git"},{"version":"3950c7865cd7c963982a2c94457182b96732f4c9","lessThan":"86e4fa65368f3bbb506dddba8c9eedc75bd603b2","status":"affected","versionType":"git"},{"version":"3950c7865cd7c963982a2c94457182b96732f4c9","lessThan":"6d532582ff3c420598f02945b13184c738cc1581","status":"affected","versionType":"git"},{"version":"3950c7865cd7c963982a2c94457182b96732f4c9","lessThan":"c57cb36f76eb7ced45f57af1a890d8f3a6d76342","status":"affected","versionType":"git"}]},{"product":"Linux","vendor":"Linux","defaultStatus":"affected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/power/supply/charger-manager.c"],"versions":[{"version":"3.7","status":"affected"},{"version":"0","lessThan":"3.7","status":"unaffected","versionType":"semver"},{"version":"6.12.109","lessThanOrEqual":"6.12.*","status":"unaffected","versionType":"semver"},{"version":"6.18.50","lessThanOrEqual":"6.18.*","status":"unaffected","versionType":"semver"},{"version":"7.2.4","lessThanOrEqual":"7.2.*","status":"unaffected","versionType":"semver"},{"version":"7.3-rc1","lessThanOrEqual":"*","status":"unaffected","versionType":"original_commit_for_fix"}]}],"cpeApplicability":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.7","versionEndExcluding":"6.12.109"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.7","versionEndExcluding":"6.18.50"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.7","versionEndExcluding":"7.2.4"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"3.7","versionEndExcluding":"7.3-rc1"}]}]}],"references":[{"url":"https://git.kernel.org/stable/c/af3ce383ba0d0d48957a22ac7058ff5698775898"},{"url":"https://git.kernel.org/stable/c/86e4fa65368f3bbb506dddba8c9eedc75bd603b2"},{"url":"https://git.kernel.org/stable/c/6d532582ff3c420598f02945b13184c738cc1581"},{"url":"https://git.kernel.org/stable/c/c57cb36f76eb7ced45f57af1a890d8f3a6d76342"}],"title":"power: supply: charger-manager: register regulators before exposing sysfs","x_generator":{"engine":"bippy-1.2.0"}}}}