CVE-2026-31731: thermal: core: Address thermal zone removal races with resume

Published May 1, 2026
·
Updated

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 thermalzonedeviceunregister() 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 thermalzonedeviceunregister() 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.

Affected Software

10 affected components
Linux Linux kernel
Linux Linux kernel>=6.8<6.12.83
Linux Linux kernel>=6.13<6.18.22
Linux Linux kernel>=6.19<6.19.12
Linux Linux kernel=7.0-rc1
Linux Linux kernel=7.0-rc2
Linux Linux kernel=7.0-rc3
Linux Linux kernel=7.0-rc4
Linux Linux kernel=7.0-rc5
Linux Linux kernel=7.0-rc6

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Configuration

    Implement the kernel thermal-core race fix: (1) move the cancel_delayed_work() call so it happens before the thermal zone object is freed, avoiding use-after-free when delayed work is re-initialized by thermal_pm_notify_complete(); (2) switch to a dedicated workqueue for thermal events and re-initialize the poll_queue delayed work for the given thermal zone; (3) flush that workqueue after poll_queue delayed work is triggered during thermal_pm_notify_complete() when the thermal zone is going away; and (4) in the second failing scenario, add a tz->state check (as described) to prevent resuming/running work during removal.

    Linux kernel thermal core poll_queue delayed work re-initialization and cancel_delayed_work()/cancel_delayed_work_sync sequencing = Move cancel_delayed_work() from the location mentioned in the text to ensure no thermal work can run after freeing the thermal zone object; use dedicated workqueue for thermal events and flush it when thermal_pm_notify_complete() calls the poll_queue delayed work if the thermal zone is going away; add tz->state check in the second failing scenario.

Event History

May 1, 2026
CVE Published
via MITRE·02:14 PM
Data Sourced
via MITRE·02:14 PM
DescriptionSeverity
Data Sourced
via NVD·03:16 PM
RemedyDescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

What level of access is required to exploit this issue?

The CVSS vector indicates local access with low privileges is required. No user interaction is required.

2

When is the vulnerable race most likely to occur?

The race involves a thermal zone being unregistered while power-management completion or resume processing reinitializes or runs its poll_queue delayed work. If that work continues after the thermal zone object is freed, it can result in a use-after-free.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203