Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'thermal-7.0-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull thermal control fixes from Rafael Wysocki:
"Address potential races between thermal zone removal and system
resume that may lead to a use-after-free (in two different ways)
and a potential use-after-free in the thermal zone unregistration
path (Rafael Wysocki)"

* tag 'thermal-7.0-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
thermal: core: Fix thermal zone device registration error path
thermal: core: Address thermal zone removal races with resume

+27 -5
+27 -5
drivers/thermal/thermal_core.c
··· 41 41 42 42 static bool thermal_pm_suspended; 43 43 44 + static struct workqueue_struct *thermal_wq __ro_after_init; 45 + 44 46 /* 45 47 * Governor section: set of functions to handle thermal governors 46 48 * ··· 315 313 if (delay > HZ) 316 314 delay = round_jiffies_relative(delay); 317 315 318 - mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, delay); 316 + mod_delayed_work(thermal_wq, &tz->poll_queue, delay); 319 317 } 320 318 321 319 static void thermal_zone_recheck(struct thermal_zone_device *tz, int error) ··· 1642 1640 device_del(&tz->device); 1643 1641 release_device: 1644 1642 put_device(&tz->device); 1643 + wait_for_completion(&tz->removal); 1645 1644 remove_id: 1646 1645 ida_free(&thermal_tz_ida, id); 1647 1646 free_tzp: ··· 1788 1785 1789 1786 guard(thermal_zone)(tz); 1790 1787 1788 + /* If the thermal zone is going away, there's nothing to do. */ 1789 + if (tz->state & TZ_STATE_FLAG_EXIT) 1790 + return; 1791 + 1791 1792 tz->state &= ~(TZ_STATE_FLAG_SUSPENDED | TZ_STATE_FLAG_RESUMING); 1792 1793 1793 1794 thermal_debug_tz_resume(tz); ··· 1818 1811 } 1819 1812 1820 1813 tz->state |= TZ_STATE_FLAG_SUSPENDED; 1814 + 1815 + /* Prevent new work from getting to the workqueue subsequently. */ 1816 + cancel_delayed_work(&tz->poll_queue); 1821 1817 } 1822 1818 1823 1819 static void thermal_pm_notify_prepare(void) ··· 1839 1829 { 1840 1830 guard(thermal_zone)(tz); 1841 1831 1842 - cancel_delayed_work(&tz->poll_queue); 1843 - 1844 1832 reinit_completion(&tz->resume); 1845 1833 tz->state |= TZ_STATE_FLAG_RESUMING; 1846 1834 ··· 1848 1840 */ 1849 1841 INIT_DELAYED_WORK(&tz->poll_queue, thermal_zone_device_resume); 1850 1842 /* Queue up the work without a delay. */ 1851 - mod_delayed_work(system_freezable_power_efficient_wq, &tz->poll_queue, 0); 1843 + mod_delayed_work(thermal_wq, &tz->poll_queue, 0); 1852 1844 } 1853 1845 1854 1846 static void thermal_pm_notify_complete(void) ··· 1871 1863 case PM_RESTORE_PREPARE: 1872 1864 case PM_SUSPEND_PREPARE: 1873 1865 thermal_pm_notify_prepare(); 1866 + /* 1867 + * Allow any leftover thermal work items already on the 1868 + * worqueue to complete so they don't get in the way later. 1869 + */ 1870 + flush_workqueue(thermal_wq); 1874 1871 break; 1875 1872 case PM_POST_HIBERNATION: 1876 1873 case PM_POST_RESTORE: ··· 1908 1895 if (result) 1909 1896 goto error; 1910 1897 1898 + thermal_wq = alloc_workqueue("thermal_events", 1899 + WQ_FREEZABLE | WQ_POWER_EFFICIENT | WQ_PERCPU, 0); 1900 + if (!thermal_wq) { 1901 + result = -ENOMEM; 1902 + goto unregister_netlink; 1903 + } 1904 + 1911 1905 result = thermal_register_governors(); 1912 1906 if (result) 1913 - goto unregister_netlink; 1907 + goto destroy_workqueue; 1914 1908 1915 1909 thermal_class = kzalloc_obj(*thermal_class); 1916 1910 if (!thermal_class) { ··· 1944 1924 1945 1925 unregister_governors: 1946 1926 thermal_unregister_governors(); 1927 + destroy_workqueue: 1928 + destroy_workqueue(thermal_wq); 1947 1929 unregister_netlink: 1948 1930 thermal_netlink_exit(); 1949 1931 error: