CVE-2026-46292
Description
Linux kernel PM domain vulnerability allows runtime PM to remain enabled after device detach, potentially causing crashes or performance issues.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Linux kernel PM domain vulnerability allows runtime PM to remain enabled after device detach, potentially causing crashes or performance issues.
Vulnerability
The Linux kernel's generic power management domain (genpd) has a vulnerability where virtual devices attached via genpd_dev_pm_attach_by_id() have pm_runtime_enable() called but lack a corresponding pm_runtime_disable() call in genpd_dev_pm_detach(). This results in virtual devices being detached from genpd while runtime power management remains enabled, contrary to design, affecting all versions where this logic exists.
Exploitation
An attacker would need to trigger the detachment of a virtual device from its PM domain while runtime power management is still enabled. The exact conditions for triggering this detachment are not detailed in the available references, but the vulnerability lies in the kernel's internal handling of device power management states.
Impact
Successful exploitation can lead to critical errors, including a NULL pointer dereference in genpd_runtime_suspend(), potentially causing system instability or crashes. In other scenarios, it may result in an unnecessary persistent vote for a device's performance state, negatively impacting power efficiency.
Mitigation
This vulnerability has been resolved by adding the missing pm_runtime_disable() call in genpd_dev_pm_detach(). The fix is available in the Linux kernel via the commit 51a7dd9cbae9210335ce398642ecaaa52c939eb5 [1]. Specific patched kernel versions are not detailed in the available references.
AI Insight generated on Jun 8, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
10707cb5df3eabpmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/base/power/domain.c+9 −2 modifieddiff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index d1dae47f3534b..5bee0a8975003 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2676,6 +2676,7 @@ static struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -2685,6 +2686,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -2710,7 +2718,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
51a7dd9cbae9pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 61c2277c9ce39..5fd08a5118cb8 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3074,6 +3074,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -3083,6 +3084,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -3108,7 +3116,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
8d44391a7f29pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 52ea84e548ff6..f9757dcb255e6 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3082,6 +3082,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -3091,6 +3092,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -3116,7 +3124,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
26735dfdd893pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 4d32fc676aaf5..71e930e80178e 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3089,6 +3089,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -3098,6 +3099,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -3123,7 +3131,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
361518a26e44pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 2643525a572bb..e4a1c63554128 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -2900,6 +2900,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -2909,6 +2910,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -2934,7 +2942,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
707cb5df3eabpmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/base/power/domain.c+9 −2 modifieddiff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index d1dae47f3534b..5bee0a8975003 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2676,6 +2676,7 @@ static struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -2685,6 +2686,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -2710,7 +2718,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
361518a26e44pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 2643525a572bb..e4a1c63554128 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -2900,6 +2900,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -2909,6 +2910,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -2934,7 +2942,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
51a7dd9cbae9pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 61c2277c9ce39..5fd08a5118cb8 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3074,6 +3074,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -3083,6 +3084,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -3108,7 +3116,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
8d44391a7f29pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 52ea84e548ff6..f9757dcb255e6 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3082,6 +3082,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -3091,6 +3092,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -3116,7 +3124,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
26735dfdd893pmdomain: core: Fix detach procedure for virtual devices in genpd
1 file changed · +9 −2
drivers/pmdomain/core.c+9 −2 modifieddiff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index 4d32fc676aaf5..71e930e80178e 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -3089,6 +3089,7 @@ static const struct bus_type genpd_bus_type = { static void genpd_dev_pm_detach(struct device *dev, bool power_off) { struct generic_pm_domain *pd; + bool is_virt_dev; unsigned int i; int ret = 0; @@ -3098,6 +3099,13 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) dev_dbg(dev, "removing from PM domain %s\n", pd->name); + /* Check if the device was created by genpd at attach. */ + is_virt_dev = dev->bus == &genpd_bus_type; + + /* Disable runtime PM if we enabled it at attach. */ + if (is_virt_dev) + pm_runtime_disable(dev); + /* Drop the default performance state */ if (dev_gpd_data(dev)->default_pstate) { dev_pm_genpd_set_performance_state(dev, 0); @@ -3123,7 +3131,7 @@ static void genpd_dev_pm_detach(struct device *dev, bool power_off) genpd_queue_power_off_work(pd); /* Unregister the device if it was created by genpd. */ - if (dev->bus == &genpd_bus_type) + if (is_virt_dev) device_unregister(dev); } -- cgit 1.3-korg
Vulnerability mechanics
Synthesis attempt was rejected by the grounding validator. Re-run pending.
References
5- git.kernel.org/stable/c/26735dfdd8930d9ef1fa92e590a9bf77726efdf6nvd
- git.kernel.org/stable/c/361518a26e4434e879db6ff43bf364795dcbfbffnvd
- git.kernel.org/stable/c/51a7dd9cbae9210335ce398642ecaaa52c939eb5nvd
- git.kernel.org/stable/c/707cb5df3eab32ddc52979418f7ace62941e6381nvd
- git.kernel.org/stable/c/8d44391a7f29e4601e8243f13498d0219bab2576nvd
News mentions
1- Linux Kernel: 25 Vulnerabilities Disclosed in Single Batch on June 8, 2026Vypr Intelligence · Jun 8, 2026