mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 01:10:04 +00:00
thermal: core: move tz->device.groups cleanup to thermal_release
The device_unregister call in thermal_zone_device_unregister causes the thermal_zone_device structure to be freed before the call to free the dynamically allocated attribute groups. This leads to a kernel panic. Furthermore, the 4 calls to free the trip point attribute structures occur before the call to unregister the device, leading to a kernel panic when sysfs attempts to access the attributes to remove them. Here is an example of a kernel panic when the cpu thermal zones are removed upon cpu offline: BUG: unable to handle kernel NULL pointer dereference at (null) IP: strlen+0x0/0x20 <snip> Call Trace: ? kernfs_name_hash+0x17/0x80 kernfs_find_ns+0x3f/0xd0 kernfs_remove_by_name_ns+0x36/0xa0 remove_files.isra.1+0x36/0x70 sysfs_remove_group+0x44/0x90 sysfs_remove_groups+0x2e/0x50 device_remove_attrs+0x5e/0x90 device_del+0x1ea/0x350 device_unregister+0x1a/0x60 thermal_zone_device_unregister+0x1f2/0x210 pkg_thermal_cpu_offline+0x14f/0x1a0 [x86_pkg_temp_thermal] ? kzalloc.constprop.2+0x10/0x10 [x86_pkg_temp_thermal] cpuhp_invoke_callback+0x8d/0x3f0 cpuhp_down_callbacks+0x42/0x80 cpuhp_thread_fun+0x8b/0xf0 smpboot_thread_fn+0x110/0x160 kthread+0x101/0x140 ? sort_range+0x30/0x30 ? kthread_park+0x90/0x90 ret_from_fork+0x25/0x30 This patch moves the kfree calls to clean up the dynamic attributes to the thermal_class's thermal_zone_device release function. Cc: Zhang Rui <rui.zhang@intel.com> Cc: Eduardo Valentin <edubezval@gmail.com> Cc: linux-pm@vger.kernel.org Cc: linux-kernel@vger.kernel.org Tested-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Signed-off-by: Jacob von Chorus <jacobvonchorus@cwphoto.ca> Signed-off-by: Zhang Rui <rui.zhang@intel.com>
This commit is contained in:
parent
7611fb6806
commit
f53345e8cf
1 changed files with 5 additions and 5 deletions
|
@ -799,6 +799,11 @@ static void thermal_release(struct device *dev)
|
|||
if (!strncmp(dev_name(dev), "thermal_zone",
|
||||
sizeof("thermal_zone") - 1)) {
|
||||
tz = to_thermal_zone(dev);
|
||||
kfree(tz->trip_type_attrs);
|
||||
kfree(tz->trip_temp_attrs);
|
||||
kfree(tz->trip_hyst_attrs);
|
||||
kfree(tz->trips_attribute_group.attrs);
|
||||
kfree(tz->device.groups);
|
||||
kfree(tz);
|
||||
} else if (!strncmp(dev_name(dev), "cooling_device",
|
||||
sizeof("cooling_device") - 1)) {
|
||||
|
@ -1305,10 +1310,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
|
|||
|
||||
thermal_zone_device_set_polling(tz, 0);
|
||||
|
||||
kfree(tz->trip_type_attrs);
|
||||
kfree(tz->trip_temp_attrs);
|
||||
kfree(tz->trip_hyst_attrs);
|
||||
kfree(tz->trips_attribute_group.attrs);
|
||||
thermal_set_governor(tz, NULL);
|
||||
|
||||
thermal_remove_hwmon_sysfs(tz);
|
||||
|
@ -1316,7 +1317,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
|
|||
idr_destroy(&tz->idr);
|
||||
mutex_destroy(&tz->lock);
|
||||
device_unregister(&tz->device);
|
||||
kfree(tz->device.groups);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
|
||||
|
||||
|
|
Loading…
Reference in a new issue