data built 2026-10-19T13:16:53Z

Look up another CVE · open CVE-2026-97903 in the interactive tracker

CVE-2026-97903

exit: hold a reference to thread_pid across proc_flush_pid

7.8 EPSS 0.1% AV:L

Published 2026-09-25 (24 days ago) by the Linux kernel CNA. Subsystem kernel. Debian urgency: unimportant.

What to do, per Debian release

Debian's own status for CVE-2026-97903 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source

ReleaseStatus VersionWhat this means
Debian 12bookwormnot affected6.1.190-1Nothing to do. bookworm never shipped the vulnerable code.
Debian 13trixienot affected6.12.113-1Nothing to do. trixie never shipped the vulnerable code.
Debian 14forkyfixed7.2.7-1Update the kernel and reboot. Fixed in 7.2.7-1. A running kernel keeps the old code until the machine restarts.
Debian unstablesidfixed7.2.7-1Update the kernel and reboot. Fixed in 7.2.7-1. A running kernel keeps the old code until the machine restarts.

The vulnerability

What the bug is

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.

Where it lives

The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.

kernel/exit.c

What this is
THE RESTMAINTAINERS section matched on */ · linux-kernel@vger.kernel.org · Buried alive in reporters
Show whether Debian builds this, per release

Debian builds this code. Every release below compiles the affected file into the kernels it ships.

  • bookworm, trixie, forky, sidy
y
built into the kernel image on every flavour - only a patch removes it

From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS Debian linux-config packages

Signals

Published
2026-09-25 (24 days ago)source
CVSS
7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it
Attack vector
local (AV:L)source
EPSS
0.12%, higher than 1.9% of all CVEssource
CISA KEV
not listedthe KEV catalogue
Debian urgency
unimportantsource
Subsystem
kernel

Upstream fixes

The versions the CNA records as introducing and fixing this, and the commit for each. source

IntroducedFixed inCommit
6.166.18.53bcb0936862f2
6.167.2.796803a12e8ac
6.167.3cdd812d0683d

Why the CNA scored it this way

Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source

AV:LAttack vector, local
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.
AC:LAttack complexity, low
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.
PR:LPrivileges required, low
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.
UI:NUser interaction, none
The attacker triggers the whole sequence with its own processes. No other user or administrator action is needed.
S:UScope, unchanged
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.
C:HConfidentiality impact, high
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.
I:HIntegrity impact, high
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.
A:HAvailability impact, high
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.