diff options
| author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2026-04-07 16:55:19 +0300 |
|---|---|---|
| committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2026-04-08 13:30:30 +0300 |
| commit | 41ff66baf81c6541f4f985dd7eac4494d03d9440 (patch) | |
| tree | dc944f76a2d37b4d3b23c7c3e2164b2c749b4136 | |
| parent | 761fdf4c8c1c0bd8427f8226be3a3eb5cf896386 (diff) | |
| download | linux-41ff66baf81c6541f4f985dd7eac4494d03d9440.tar.xz | |
thermal: core: Fix thermal zone governor cleanup issues
If thermal_zone_device_register_with_trips() fails after adding
a thermal governor to the thermal zone being registered, the
governor is not removed from it as appropriate which may lead to
a memory leak.
In turn, thermal_zone_device_unregister() calls thermal_set_governor()
without acquiring the thermal zone lock beforehand which may race with
a governor update via sysfs and may lead to a use-after-free in that
case.
Address these issues by adding two thermal_set_governor() calls, one to
thermal_release() to remove the governor from the given thermal zone,
and one to the thermal zone registration error path to cover failures
preceding the thermal zone device registration.
Fixes: e33df1d2f3a0 ("thermal: let governors have private data for each thermal zone")
Cc: All applicable <stable@vger.kernel.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Link: https://patch.msgid.link/5092923.31r3eYUQgx@rafael.j.wysocki
| -rw-r--r-- | drivers/thermal/thermal_core.c | 7 |
1 files changed, 4 insertions, 3 deletions
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c index b6b651cb2331..6e10b2fe2972 100644 --- a/drivers/thermal/thermal_core.c +++ b/drivers/thermal/thermal_core.c @@ -964,6 +964,7 @@ static void thermal_release(struct device *dev) sizeof("thermal_zone") - 1)) { tz = to_thermal_zone(dev); thermal_zone_destroy_device_groups(tz); + thermal_set_governor(tz, NULL); mutex_destroy(&tz->lock); complete(&tz->removal); } else if (!strncmp(dev_name(dev), "cooling_device", @@ -1610,8 +1611,10 @@ thermal_zone_device_register_with_trips(const char *type, /* sys I/F */ /* Add nodes that are always present via .groups */ result = thermal_zone_create_device_groups(tz); - if (result) + if (result) { + thermal_set_governor(tz, NULL); goto remove_id; + } result = device_register(&tz->device); if (result) @@ -1724,8 +1727,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) cancel_delayed_work_sync(&tz->poll_queue); - thermal_set_governor(tz, NULL); - thermal_thresholds_exit(tz); thermal_remove_hwmon_sysfs(tz); ida_free(&thermal_tz_ida, tz->id); |
