In the Linux kernel, the following vulnerability has been resolved:
thermal: core: Address thermal zone removal races with resume
Since thermalzonepmcomplete() and thermalzonedeviceresume() re-initialize the pollqueue delayed work for the given thermal zone, the canceldelayedworksync() in thermalzonedevice_unregister() may miss some already running work items and the thermal zone may be freed prematurely [1].
There are two failing scenarios that both start with running thermalpmnotifycomplete() right before invoking thermalzonedeviceunregister() for one of the thermal zones.
In the first scenario, there is a work item already running for the given thermal zone when thermalpmnotifycomplete() calls thermalzonepmcomplete() for that thermal zone and it continues to run when thermalzonedeviceunregister() starts. Since the pollqueue delayed work has been re-initialized by thermalpmnotifycomplete(), the running work item will be missed by the canceldelayedworksync() in thermalzonedevice_unregister() and if it continues to run past the freeing of the thermal zone object, a use-after-free will occur.
In the second scenario, thermalzonedeviceresume() queued up by thermalpmnotifycomplete() runs right after the thermalzoneexit() called by thermalzonedeviceunregister() has returned. The pollqueue delayed work is re-initialized by it before canceldelayedworksync() is called by thermalzonedeviceunregister(), so it may continue to run after the freeing of the thermal zone object, which also leads to a use-after-free.
Address the first failing scenario by ensuring that no thermal work items will be running when thermalpmnotifycomplete() is called. For this purpose, first move the canceldelayedwork() call from thermalzonepmcomplete() to thermalzonepmprepare() to prevent new work from entering the workqueue going forward. Next, switch over to using a dedicated workqueue for thermal events and update the code in thermalpmnotify() to flush that workqueue after thermalpmnotifyprepare() has returned which will take care of all leftover thermal work already on the workqueue (that leftover work would do nothing useful anyway because all of the thermal zones have been flagged as suspended).
The second failing scenario is addressed by adding a tz->state check to thermalzonedeviceresume() to prevent it from re-initializing the pollqueue delayed work if the thermal zone is going away.
Note that the above changes will also facilitate relocating the suspend and resume of thermal zones closer to the suspend and resume of devices, respectively.
{
"osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/31xxx/CVE-2026-31731.json",
"cna_assigner": "Linux"
}