Sceawere
Vulnerability Detail
CVE-2026-98260UPDATED Verified Sceawere Triage Sources: NVD / CISA KEV
Linux Kernel Use-After-Free in POSIX Timers
Vulnerability Metadata
- Severity
- High
- Score / CVSS
- 7.8
- Creation Date
- 1d ago
- Vendor
- Linux
- Product
- Linux
- Attack Type
- N/A
- Vector String
- CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Attack Complexity
- LOW
Narrative and Response
Description
In the Linux kernel, the following vulnerability has been resolved: exec: Cleanup POSIX timers right after de_thread() A per-thread CPU timer holds a reference to the PID of the thread it is attached to and, while it is armed, its node is queued in that thread's posix_cputimers. The task is looked up by that PID. When a non-leader thread exec()s, de_thread() changes which task owns that PID. pid_task(timer->it.cpu.pid, PIDTYPE_PID) then returns NULL, but the node is still queued on tsk, which is alive. timer_lock_sighand() takes a failed lookup to mean that the node is already dequeued, so it has nothing to undo. begin_new_exec() calls posix_cpu_timers_exit(me) right after exec_task_namespaces() and that removes the leftover node, so the state normally stays invisible. But bprm->point_of_no_return is set before de_thread(), so if unshare_files(), set_mm_exe_file(), exec_mmap() or exec_task_namespaces() fails, the task dies before it gets there. exit_itimers() then frees the k_itimer while its node is still queued, and reaping tsk later erases that freed node from the rbtree. In short: the non-leader thread B the parent timer_create(CLOCK_THREAD_CPUTIME_ID) timer_settime() arm_timer() // the node is queued on B execve() de_thread(B) exchange_tids(B, leader) // B's PID now belongs to the leader release_task(leader) __exit_signal(leader) posix_cpu_timers_exit(leader) // cleans leader's queue, not B's __unhash_process(leader) // that PID has no task anymore exec_mmap() mmap_read_lock_killable(old_mm) kill(B, SIGKILL) // -EINTR get_signal() do_exit() exit_itimers() posix_timer_delete() posix_cpu_timer_del() posix_timer_unhash_and_free() // freed while still queued wait4() release_task(B) posix_cpu_timers_exit(B) cleanup_timerqueue() timerqueue_del() // use-after-free Move the POSIX timer cleanup right after de_thread() before any of the later failure conditions brings the task into do_exit(). [ tglx: Move the cleanup right after de_thread() ]
Executive Summary
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Technical Details
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Mitigations
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
References
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Additional Metadata
{
"score": "7.8",
"pubDate": "2026-10-06T09:18:15.040Z",
"pubdate": "2026-10-06T09:18:15.040Z",
"executiveSummary": "This vulnerability is a use-after-free (UAF) flaw located within the Linux kernel's POSIX CPU timer subsystem, specifically triggered during the execve() system call process.\nThe issue arises when a non-leader thread performs an execve() operation. If the execution process fails at specific points after de_thread() but before the final task cleanup, the task may terminate via do_exit().\nUnder these conditions, exit_itimers() frees the POSIX timer structure while the corresponding timer node remains queued in the thread's posix_cputimers rbtree. Subsequent task reaping leads to a use-after-free during the cleanup of the timer queue.\nThe vulnerability affects the Linux kernel and poses a local privilege escalation or system instability risk. An attacker capable of triggering complex execve() failure scenarios could potentially leverage this memory corruption to crash the system or achieve arbitrary code execution, depending on kernel memory layout and heap state.\nExploitation requires a local attacker to possess the ability to spawn threads and induce specific error conditions during the execve() sequence, such as memory map failures or signal interruptions.",
"technicalDetails": "The root cause is a lifecycle mismatch between the POSIX timer nodes and the thread-specific timer queues during the execve() transition. Per-thread CPU timers maintain a reference to the task's PID and reside in the posix_cputimers rbtree. During a multi-threaded process's execve(), de_thread() is invoked to reorganize the thread group, transferring PID ownership to the new leader.\nWhen de_thread() completes, the internal PID mapping changes. However, if the execve() process encounters an error in functions such as unshare_files(), set_mm_exe_file(), or exec_mmap() after the process has reached its 'point of no return' (bprm->point_of_no_return), the task enters an error-handling path that leads to do_exit().\nThe critical flow is as follows: When the task calls exit_itimers() during do_exit(), it invokes posix_timer_delete() and subsequently posix_timer_unhash_and_free(). This process frees the memory associated with the k_itimer structure. Crucially, the timer node remains linked within the task's posix_cputimers rbtree because the timer cleanup (posix_cpu_timers_exit) has not yet been triggered for the specific thread undergoing the transition.\nWhen the task is eventually reaped via release_task(), the kernel calls posix_cpu_timers_exit(), which attempts to iterate over and remove nodes from the rbtree using timerqueue_del(). Because the memory for the timer node was already deallocated during exit_itimers(), the kernel performs a write or read operation on freed memory, resulting in a use-after-free condition.\nThe vulnerable component is the interaction between execve()-related task transitions in fs/exec.c and the timer management logic in kernel/time/posix-cpu-timers.c. The exploit window is opened by the temporal gap between the modification of the thread's process identity and the final cleanup of the associated POSIX timers. By forcing a signal (e.g., SIGKILL) or a resource exhaustion error after the PID transfer but before the thread reaches the intended timer cleanup function, an attacker can reliably cause the kernel to access stale memory pointers.\nPost-exploitation impact includes kernel panic, memory corruption leading to system instability, or potential exploitation of the freed object to gain control of execution flow, though this is highly dependent on heap grooming and kernel protection mechanisms."
}