CVE-2026-45925
Description
In the Linux kernel, the following vulnerability has been resolved:
thermal/of: Fix reference leak in thermal_of_cm_lookup()
In thermal_of_cm_lookup(), tr_np is obtained via of_parse_phandle(), but never released.
Use the __free(device_node) cleanup attribute to automatically release the node and fix the leak.
[ rjw: Changelog edits ]
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
A reference leak in Linux kernel's thermal_of_cm_lookup() due to missing of_node_put() on tr_np can cause resource exhaustion.
Vulnerability
The Linux kernel's thermal subsystem contains a reference leak in the thermal_of_cm_lookup() function. The function obtains a device node pointer tr_np via of_parse_phandle(), which increments the reference count of the node, but never releases it with of_node_put(). This bug affects all kernel versions that include the commit introducing this code path; the fix is applied in the stable tree as commit a1fe789a96fe (referenced in [1]).
Exploitation
An attacker does not need any special privileges or network access, because the vulnerability is triggered by normal thermal zone registration during system boot or device enumeration. Any system that uses device tree-based thermal management will hit the code path in thermal_of_cm_lookup(). The missing release causes a slow, cumulative reference count increment each time the function is called, eventually leading to exhaustion of device node references.
Impact
Successful exploitation results in resource exhaustion (memory leak and inability to release device nodes), which can cause degraded system performance and eventually lead to denial of service (system instability or hang) due to kernel memory starvation. No confidentiality or integrity impact is expected.
Mitigation
The fix was incorporated into the Linux kernel stable tree as commit a1fe789a96fe47733c133134fd264cb7ca832395 [1]. Users should apply the latest stable kernel updates that include this commit. As a workaround, systems not using device tree-based thermal management are not affected. The vulnerability is not known to be listed on CISA's KEV.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
8a1fe789a96fethermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 1a51a4d240ff60..b6d0c92f5522bd 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -280,10 +280,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
025796ccd7f9thermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 1a51a4d240ff60..b6d0c92f5522bd 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -280,10 +280,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
8af710156c53thermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index e0aa9d9d5604b7..3e674f2d66316e 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -299,10 +299,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
8344d5da9df7thermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 1a51a4d240ff60..b6d0c92f5522bd 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -280,10 +280,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
8af710156c53thermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index e0aa9d9d5604b7..3e674f2d66316e 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -299,10 +299,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
a1fe789a96fethermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 1a51a4d240ff60..b6d0c92f5522bd 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -280,10 +280,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
025796ccd7f9thermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 1a51a4d240ff60..b6d0c92f5522bd 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -280,10 +280,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
8344d5da9df7thermal/of: Fix reference leak in thermal_of_cm_lookup()
1 file changed · +2 −3
drivers/thermal/thermal_of.c+2 −3 modifieddiff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 1a51a4d240ff60..b6d0c92f5522bd 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -280,10 +280,10 @@ static bool thermal_of_cm_lookup(struct device_node *cm_np, struct cooling_spec *c) { for_each_child_of_node_scoped(cm_np, child) { - struct device_node *tr_np; int count, i; - tr_np = of_parse_phandle(child, "trip", 0); + struct device_node *tr_np __free(device_node) = + of_parse_phandle(child, "trip", 0); if (tr_np != trip->priv) continue; -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing `of_node_put()` call after `of_parse_phandle()` in `thermal_of_cm_lookup()` causes a device-node reference leak."
Attack vector
An attacker who can trigger thermal device-tree parsing (e.g., by loading a thermal zone or cooling device) causes `thermal_of_cm_lookup()` to be called. Each call obtains a `struct device_node` via `of_parse_phandle()` without releasing it, leaking a reference to the kernel's device node reference count. Over repeated invocations this exhausts the reference counter, preventing the node from being freed and potentially leading to resource exhaustion or denial of service. No special privileges are required beyond the ability to trigger thermal binding lookups.
Affected code
The vulnerability is in the `thermal_of_cm_lookup()` function in `drivers/thermal/thermal_of.c` [patch_id=2661272]. The function obtains a device node reference via `of_parse_phandle(child, "trip", 0)` but never releases it, causing a reference leak on every call.
What the fix does
The patch replaces the bare `struct device_node *tr_np` declaration with `struct device_node *tr_np __free(device_node)`, which uses the Linux kernel's automatic cleanup attribute. When `tr_np` goes out of scope (at the end of each `for_each_child_of_node_scoped` iteration), the `__free(device_node)` attribute automatically calls `of_node_put()` to release the reference obtained by `of_parse_phandle()`. This closes the leak without adding explicit `of_node_put()` calls.
Preconditions
- configThe system must have device-tree thermal zones with cooling maps that reference trip points via the 'trip' phandle property.
- inputAn attacker must be able to trigger thermal binding lookups, e.g., by loading/unloading thermal drivers or triggering thermal zone re-evaluation.
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.