GHSA-2RJF-492G-58R9
Vulnerability from github – Published: 2026-08-22 18:30 – Updated: 2026-08-25 06:31In the Linux kernel, the following vulnerability has been resolved:
sched/psi: Shut down rtpoll_timer in psi_cgroup_free()
psi_schedule_rtpoll_work() is called locklessly from the scheduler hotpath and can race psi_trigger_destroy() taking down the last rtpoll trigger under rtpoll_trigger_lock:
psi_schedule_rtpoll_work() psi_trigger_destroy()
rcu_read_lock(); task = rcu_dereference(rtpoll_task); rcu_assign_pointer(rtpoll_task, NULL); timer_delete(&rtpoll_timer); mod_timer(&rtpoll_timer, ...); rcu_read_unlock(); synchronize_rcu(); kthread_stop(task_to_destroy);
The group can then be freed with the re-armed timer still pending, and poll_timer_fn() runs on freed memory.
461daba06bdc ("psi: eliminate kthread_worker from psi trigger scheduling mechanism") deleted the timer synchronously after the synchronize_rcu(), which prevented this but raced trigger creation instead: the deletion could cancel the timer that a new trigger set armed during the grace period and, as creation also reinitialized the timer at the time, corrupt it. 8f91efd870ea ("psi: Fix race between psi_trigger_create/destroy") moved the initialization into group_init() and the deletion into the locked section, trading the creation races for the window above.
Neither placement in the destruction path works. A pending timer firing while the group is alive is harmless though. poll_timer_fn() just wakes the rtpoll waitqueue and doesn't re-arm itself. Bind the timer to the group's lifetime instead and shut it down in psi_cgroup_free(). Nothing can arm it by then. timer_shutdown_sync() because the timer is never armed again.
{
"affected": [],
"aliases": [
"CVE-2026-74594"
],
"database_specific": {
"cwe_ids": [],
"github_reviewed": false,
"github_reviewed_at": null,
"nvd_published_at": "2026-08-22T16:16:31Z",
"severity": "HIGH"
},
"details": "In the Linux kernel, the following vulnerability has been resolved:\n\nsched/psi: Shut down rtpoll_timer in psi_cgroup_free()\n\npsi_schedule_rtpoll_work() is called locklessly from the scheduler hotpath\nand can race psi_trigger_destroy() taking down the last rtpoll trigger under\nrtpoll_trigger_lock:\n\n psi_schedule_rtpoll_work() psi_trigger_destroy()\n\n rcu_read_lock();\n task = rcu_dereference(rtpoll_task);\n rcu_assign_pointer(rtpoll_task, NULL);\n timer_delete(\u0026rtpoll_timer);\n mod_timer(\u0026rtpoll_timer, ...);\n rcu_read_unlock();\n synchronize_rcu();\n kthread_stop(task_to_destroy);\n\nThe group can then be freed with the re-armed timer still pending, and\npoll_timer_fn() runs on freed memory.\n\n461daba06bdc (\"psi: eliminate kthread_worker from psi trigger scheduling\nmechanism\") deleted the timer synchronously after the synchronize_rcu(),\nwhich prevented this but raced trigger creation instead: the deletion could\ncancel the timer that a new trigger set armed during the grace period and,\nas creation also reinitialized the timer at the time, corrupt it.\n8f91efd870ea (\"psi: Fix race between psi_trigger_create/destroy\") moved the\ninitialization into group_init() and the deletion into the locked section,\ntrading the creation races for the window above.\n\nNeither placement in the destruction path works. A pending timer firing\nwhile the group is alive is harmless though. poll_timer_fn() just wakes the\nrtpoll waitqueue and doesn\u0027t re-arm itself. Bind the timer to the group\u0027s\nlifetime instead and shut it down in psi_cgroup_free(). Nothing can arm it\nby then. timer_shutdown_sync() because the timer is never armed again.",
"id": "GHSA-2rjf-492g-58r9",
"modified": "2026-08-25T06:31:21Z",
"published": "2026-08-22T18:30:25Z",
"references": [
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2026-74594"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/1e5ca82eee59caca6988f9d6e859786aab8a5fa0"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/310b5a537a78c358a4cd244bd767c1a517a05459"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/4addb102154b7cf6e2310ccbe20c3c08619e520d"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/5457025fa8ca3c0d2732109513de839e3e797190"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/611e7821c4f83a671455658797336faecc3a5196"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/8037c5b2b2a447df52542f4d8535895d837bdcbd"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/806fcff98c1d7cb3c1dc0015e55ebdbe819e6b08"
},
{
"type": "WEB",
"url": "https://git.kernel.org/stable/c/894a9300d7fb2e2951da92e565ae6de7ddfb0a69"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"type": "CVSS_V3"
}
]
}
Sightings
| Author | Source | Type | Date | Other |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.
The approach is described in our paper Mapping CVEs to MITRE ATT&CK Techniques: A Curated Gold-Set Classifier and the Limits of LLM-Assisted Label Expansion.