CVE-2026-97903
📛 CVE Title
exit: hold a reference to thread_pid across proc_flush_pid
Description
In the Linux kernel, the following vulnerability has been resolved: exit: hold a reference to thread_pid across proc_flush_pid Commit 0a36bad01731 ("release_task: kill the no longer needed get/put_pid(thread_pid)") removed the reference around proc_flush_pid(). It assumed that free_pids(post.pids) at the end of release_task() would keep thread_pid alive until then. That assumption is wrong. __change_pid() only records a detached PID in post.pids when pid_has_task() is false for every PIDTYPE. If another task still uses the exiting task's PID as its process group or session ID, __unhash_process() removes the exiting task's PIDTYPE_PID link but leaves the PID out of post.pids. release_task() therefore holds no reference to it after dropping tasklist_lock. The other task can then remove the remaining PIDTYPE links. Its free_pids() call schedules delayed_put_pid(), and the RCU callback can free the PID before the first release_task() reaches proc_flush_pid(). An unprivileged reproducer races wait4(-1) against setsid() to trigger this ordering. Three of three fresh v7.2 KASAN boots reported: BUG: KASAN: slab-use-after-free in proc_invalidate_siblings_dcache+0x3e2/0x3f0 Read of size 8 by task h7_pid_reaper/1921 Call Trace: proc_invalidate_siblings_dcache release_task wait_consider_task __do_wait do_wait kernel_wait4 Freed by task 0: kmem_cache_free put_pid delayed_put_pid rcu_core Last potentially related work creation: __call_rcu_common free_pids ksys_setsid KASAN identified a 144-byte object from the pid cache and located the bad read 80 bytes into the freed object, matching pid->inodes. With an explicit reference, three of three fresh boots completed without a KASAN report. The concurrent RCU callback dropped its reference while proc_flush_pid() was protected, and the balancing put_pid() performed the final free afterward. Take a reference before __unhash_process() clears p->thread_pid and release it after proc_flush_pid() completes. A tested source reproducer is available privately on request. No controlled read or write, information leak, or privilege escalation is claimed. The mainline patch applies directly to v6.19.y and newer; v6.16.y through v6.18.y need a context-adjusted backport.
Overview
- State
- PUBLISHED
- Assigner (CNA)
- Linux
- CVSS severity
- HIGH
- CVSS score
- 7.8 / 10
- CVSS vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H- Effective score
- 7.8 / 10 HIGH source: CNA overview
- CWE(s)
- —
- Reserved
- 2026-09-25
- Published
- 2026-09-25 10:22 UTC
- Last updated
- 2026-09-25 14:41 UTC
- Source
- https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/97xxx/CVE-2026-97903.json
- Linked Threat
- CVE-2026-97903 — exit: hold a reference to thread_pid across proc_flush_pid
NVD triage scoring NVD CVE 2.0
Layer NVD adds on top of the CNA's CVE record — published / last-modified timestamps, exploitability / impact subscores, and the FIRST.org EPSS probability that this CVE will be exploited in the wild in the next 30 days.
- NVD published
- 2026-09-25 11:17:17 UTC
- NVD last modified
- 2026-09-25 15:18:01 UTC
- NVD CVSS v3.1
- 7.8 / 10 HIGH source: 416baaa9-dc9f-4396-8d5f-8c081fb06d67
- NVD CVSS vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H- Exploitability subscore
- 1.8 / 10
- Impact subscore
- 5.9 / 10
NVD / KEV / EPSS data refreshed 2026-09-26 04:28 UTC. Re-run the 🛰 Backfill from NVD button above to refresh.
Affected products (2)
| Vendor | Product | Versions | Platforms |
|---|---|---|---|
| Linux | Linux |
0a36bad01731e71568bdd365764d38b6bd576ab0 (affected),
0a36bad01731e71568bdd365764d38b6bd576ab0 (affected),
0a36bad01731e71568bdd365764d38b6bd576ab0 (affected)
|
— |
| Linux | Linux |
6.16 (affected),
0 (unaffected),
6.18.53 (unaffected),
7.2.7 (unaffected),
7.3-rc3 (unaffected)
|
— |
Vendor references (3)
References embedded in the original CVE record by the assigning CNA.
Web references (0)
DuckDuckGo results ranked by threat-intel / vendor advisory domains. Generated by the 🔎 Find references (web) button above — same flow as the Remediations search.
No web references attached yet.
NVD-tagged references (3)
Reference list NVD curates from the CNA record, vendor advisories, and third-party reports. The tag chips below are NVD's analyst-assigned categories.
- https://git.kernel.org/stable/c/96803a12e8ac15f0a1b4b151db59038f12304e58 416baaa9-dc9f-4396-8d5f-8c081fb06d67
- https://git.kernel.org/stable/c/bcb0936862f2b653114d9bd582ca26990ef54a64 416baaa9-dc9f-4396-8d5f-8c081fb06d67
- https://git.kernel.org/stable/c/cdd812d0683dee14ead02c9eded568685e61b23f 416baaa9-dc9f-4396-8d5f-8c081fb06d67
AI Forensic Analysis
Only Available for Registered Users. Sign in to view.
Raw JSON
The full cvelistV5 record. Download as CVE-2026-97903.json.
{
"containers": {
"cna": {
"affected": [
{
"defaultStatus": "unaffected",
"product": "Linux",
"programFiles": [
"kernel/exit.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"lessThan": "bcb0936862f2b653114d9bd582ca26990ef54a64",
"status": "affected",
"version": "0a36bad01731e71568bdd365764d38b6bd576ab0",
"versionType": "git"
},
{
"lessThan": "96803a12e8ac15f0a1b4b151db59038f12304e58",
"status": "affected",
"version": "0a36bad01731e71568bdd365764d38b6bd576ab0",
"versionType": "git"
},
{
"lessThan": "cdd812d0683dee14ead02c9eded568685e61b23f",
"status": "affected",
"version": "0a36bad01731e71568bdd365764d38b6bd576ab0",
"versionType": "git"
}
]
},
{
"defaultStatus": "affected",
"product": "Linux",
"programFiles": [
"kernel/exit.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"status": "affected",
"version": "6.16"
},
{
"lessThan": "6.16",
"status": "unaffected",
"version": "0",
"versionType": "semver"
},
{
"lessThanOrEqual": "6.18.*",
"status": "unaffected",
"version": "6.18.53",
"versionType": "semver"
},
{
"lessThanOrEqual": "7.2.*",
"status": "unaffected",
"version": "7.2.7",
"versionType": "semver"
},
{
"lessThanOrEqual": "*",
"status": "unaffected",
"version": "7.3-rc3",
"versionType": "original_commit_for_fix"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "6.18.53",
"versionStartIncluding": "6.16",
"vulnerable": true
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "7.2.7",
"versionStartIncluding": "6.16",
"vulnerable": true
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "7.3-rc3",
"versionStartIncluding": "6.16",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\nexit: hold a reference to thread_pid across proc_flush_pid\n\nCommit 0a36bad01731 (\"release_task: kill the no longer needed\nget/put_pid(thread_pid)\") removed the reference around proc_flush_pid().\nIt assumed that free_pids(post.pids) at the end of release_task() would\nkeep thread_pid alive until then.\n\nThat assumption is wrong. __change_pid() only records a detached PID in\npost.pids when pid_has_task() is false for every PIDTYPE. If another task\nstill uses the exiting task's PID as its process group or session ID,\n__unhash_process() removes the exiting task's PIDTYPE_PID link but leaves\nthe PID out of post.pids. release_task() therefore holds no reference to\nit after dropping tasklist_lock.\n\nThe other task can then remove the remaining PIDTYPE links. Its\nfree_pids() call schedules delayed_put_pid(), and the RCU callback can free\nthe PID before the first release_task() reaches proc_flush_pid().\n\nAn unprivileged reproducer races wait4(-1) against setsid() to trigger this\nordering. Three of three fresh v7.2 KASAN boots reported:\n\n BUG: KASAN: slab-use-after-free in\n proc_invalidate_siblings_dcache+0x3e2/0x3f0\n Read of size 8 by task h7_pid_reaper/1921\n\n Call Trace:\n proc_invalidate_siblings_dcache\n release_task\n wait_consider_task\n __do_wait\n do_wait\n kernel_wait4\n\n Freed by task 0:\n kmem_cache_free\n put_pid\n delayed_put_pid\n rcu_core\n\n Last potentially related work creation:\n __call_rcu_common\n free_pids\n ksys_setsid\n\nKASAN identified a 144-byte object from the pid cache and located the bad\nread 80 bytes into the freed object, matching pid->inodes. With an\nexplicit reference, three of three fresh boots completed without a KASAN\nreport. The concurrent RCU callback dropped its reference while\nproc_flush_pid() was protected, and the balancing put_pid() performed the\nfinal free afterward.\n\nTake a reference before __unhash_process() clears p->thread_pid and release\nit after proc_flush_pid() completes.\n\nA tested source reproducer is available privately on request. No\ncontrolled read or write, information leak, or privilege escalation is\nclaimed. The mainline patch applies directly to v6.19.y and newer;\nv6.16.y through v6.18.y need a context-adjusted backport."
}
],
"metrics": [
{
"cvssV3_1": {
"baseScore": 7.8,
"baseSeverity": "HIGH",
"vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"version": "3.1"
},
"scenarios": [
{
"lang": "en",
"value": "AV:L - The freed struct pid is reached through release_task() -> proc_flush_pid() when a local process reaps a child via wait4()/waitid(), racing with ksys_setsid() in another local process; no network or remote data is involved.\nAC:L - The attacker controls both sides of the race: its own parent calls wait4(-1) on an exiting process-group leader while its own child, still in that pgrp, calls setsid() to drop the last PID link. The loop can be retried without limit, and syzbot plus the author's reproducer hit it reliably.\nPR:L - Needs only an ordinary local account able to fork, setpgid/setsid and wait4 its own children. There is no capability check anywhere on the release_task()/ksys_setsid() path.\nUI:N - The attacker triggers the whole sequence with its own processes. No other user or administrator action is needed.\nS:U - This is memory corruption inside the kernel's own pid/procfs bookkeeping, which stays within the kernel security authority; no VM or hardware isolation boundary is crossed.\nC:H - proc_invalidate_siblings_dcache() reads pid->inodes from the freed struct pid and follows it as a proc_inode pointer (igrab, d_find_alias). With the slot reclaimed by attacker-shaped data, that use-after-free lets the attacker dereference pointers it controls, which supports kernel memory disclosure.\nI:H - On the freed object the function takes spin_lock(&pid->lock) and runs hlist_del_init_rcu() on node pointers taken from it, which are unlink-style writes. It then calls igrab/iput/d_invalidate on an inode it derived from freed memory, a use-after-free write primitive usable for memory corruption.\nA:H - KASAN reports a slab-use-after-free in proc_invalidate_siblings_dcache from release_task. Without KASAN, the list walk or igrab on a reallocated pid slot can oops or corrupt the dcache and crash the kernel."
}
]
}
],
"providerMetadata": {
"dateUpdated": "2026-09-25T14:41:35.285Z",
"orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"shortName": "Linux"
},
"references": [
{
"url": "https://git.kernel.org/stable/c/bcb0936862f2b653114d9bd582ca26990ef54a64"
},
{
"url": "https://git.kernel.org/stable/c/96803a12e8ac15f0a1b4b151db59038f12304e58"
},
{
"url": "https://git.kernel.org/stable/c/cdd812d0683dee14ead02c9eded568685e61b23f"
}
],
"title": "exit: hold a reference to thread_pid across proc_flush_pid",
"x_generator": {
"engine": "bippy-1.2.0"
}
}
},
"cveMetadata": {
"assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"assignerShortName": "Linux",
"cveId": "CVE-2026-97903",
"datePublished": "2026-09-25T10:22:29.852Z",
"dateReserved": "2026-09-25T10:18:58.200Z",
"dateUpdated": "2026-09-25T14:41:35.285Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}