Skip to content

Commit 37a430a

Browse files
rafaeljwgregkh
authored andcommitted
thermal: core: Fix thermal zone governor cleanup issues
[ Upstream commit 41ff66b ] 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: e33df1d ("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 [ kept the `thermal_zone_create_device_groups(tz, mask)` signature when adding the new failure-path cleanup ] Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 78509c4 commit 37a430a

1 file changed

Lines changed: 4 additions & 3 deletions

File tree

drivers/thermal/thermal_core.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ static void thermal_release(struct device *dev)
804804
sizeof("thermal_zone") - 1)) {
805805
tz = to_thermal_zone(dev);
806806
thermal_zone_destroy_device_groups(tz);
807+
thermal_set_governor(tz, NULL);
807808
mutex_destroy(&tz->lock);
808809
complete(&tz->removal);
809810
} else if (!strncmp(dev_name(dev), "cooling_device",
@@ -1325,8 +1326,10 @@ thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *t
13251326
/* sys I/F */
13261327
/* Add nodes that are always present via .groups */
13271328
result = thermal_zone_create_device_groups(tz, mask);
1328-
if (result)
1329+
if (result) {
1330+
thermal_set_governor(tz, NULL);
13291331
goto remove_id;
1332+
}
13301333

13311334
/* A new thermal zone needs to be updated anyway. */
13321335
atomic_set(&tz->need_update, 1);
@@ -1478,8 +1481,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
14781481

14791482
cancel_delayed_work_sync(&tz->poll_queue);
14801483

1481-
thermal_set_governor(tz, NULL);
1482-
14831484
thermal_remove_hwmon_sysfs(tz);
14841485
ida_free(&thermal_tz_ida, tz->id);
14851486
ida_destroy(&tz->ida);

0 commit comments

Comments
 (0)