Use-after-free / memory safety in PM domain detach and regmap handling
Description
The commit fixes use-after-free / memory safety issues in the pmdomain (power management domains) subsystem:
- genpd detach fix (drivers/pmdomain/core.c): When detaching devices, the code now distinguishes virtual devices created by genpd and disables runtime PM for them, and only unregisters devices that were created by genpd. This prevents premature frees or invalid dereferences during detachment of virtual devices, addressing a potential use-after-free during lifecycle handling of PM domains.
- scpsys bus protection path fix (drivers/pmdomain/mediatek/mtk-pm-domains.c): In scpsys_get_bus_protection_legacy(), the patch introduces an explicit return path using a ret variable and ensures of_node_put(node) is released before returning on error. This prevents a use-after-free or use-after-release scenario stemming from improper resource/lifetimes management when looking up regmaps for legacy bus protection.
Together these changes fix a memory-safety vulnerability in PM domain detach and legacy bus-protection lookup, reducing risk of use-after-free leading to crashes or potential privilege/escalation opportunities under certain device lifecycle sequences.
Commit Details
Author: Linus Torvalds
Date: 2026-05-07 15:43 UTC
Message:
Merge tag 'pmdomain-v7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm
Pull pmdomain fixes from Ulf Hansson:
- Fix detach procedure for virtual devices in genpd
- mediatek: Fix use-after-free in scpsys_get_bus_protection_legacy()
* tag 'pmdomain-v7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm:
pmdomain: mediatek: fix use-after-free in scpsys_get_bus_protection_legacy()
pmdomain: core: Fix detach procedure for virtual devices in genpd
Triage Assessment
Vulnerability Type: Use-after-free (memory safety)
Confidence: HIGH
Reasoning:
The commit includes a fix for a use-after-free in scpsys_get_bus_protection_legacy() and adjusts detach logic for virtual devices in genpd. Use-after-free is a memory safety vulnerability that can lead to security issues, and the changes address lifecycle management and error paths to prevent premature frees and invalid accesses. This constitutes a security-related fix beyond typical refactoring.
Verification Assessment
Vulnerability Type: Use-after-free / memory safety in PM domain detach and regmap handling
Confidence: HIGH
Affected Versions: < v7.1-rc1
Code Diff
diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
index 4d32fc676aaf53..71e930e80178e9 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);
}
diff --git a/drivers/pmdomain/mediatek/mtk-pm-domains.c b/drivers/pmdomain/mediatek/mtk-pm-domains.c
index d2b8d033295153..e1cfd42234734f 100644
--- a/drivers/pmdomain/mediatek/mtk-pm-domains.c
+++ b/drivers/pmdomain/mediatek/mtk-pm-domains.c
@@ -1015,6 +1015,7 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
struct device_node *node, *smi_np;
int num_regmaps = 0, i, j;
struct regmap *regmap[3];
+ int ret = 0;
/*
* Legacy code retrieves a maximum of three bus protection handles:
@@ -1065,11 +1066,14 @@ static int scpsys_get_bus_protection_legacy(struct device *dev, struct scpsys *s
if (node) {
regmap[2] = syscon_regmap_lookup_by_phandle(node, "mediatek,infracfg-nao");
num_regmaps++;
- of_node_put(node);
- if (IS_ERR(regmap[2]))
- return dev_err_probe(dev, PTR_ERR(regmap[2]),
+ if (IS_ERR(regmap[2])) {
+ ret = dev_err_probe(dev, PTR_ERR(regmap[2]),
"%pOF: failed to get infracfg regmap\n",
node);
+ of_node_put(node);
+ return ret;
+ }
+ of_node_put(node);
} else {
regmap[2] = NULL;
}