Bug 2546491 (CVE-2026-98260)
| Summary: | CVE-2026-98260 kernel: exec: Cleanup POSIX timers right after de_thread() | ||
|---|---|---|---|
| Product: | [Other] Security Response | Reporter: | OSIDB Bzimport <bzimport> |
| Component: | vulnerability | Assignee: | Product Security DevOps Team <prodsec-dev> |
| Status: | NEW --- | QA Contact: | |
| Severity: | high | Docs Contact: | |
| Priority: | high | ||
| Version: | unspecified | CC: | akhatavk, akito5623, aos-team-art-private, asdas, dpaolell, jdelft, jupierce, lgarciaa, mbiarnes, ppalepu, ppostler, prdhamdh, rhel-process-autobot, sghai, sidsharm, suppawar, vlaad, watson-tool-maintainers |
| Target Milestone: | --- | Keywords: | Security |
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | Doc Type: | --- | |
| Doc Text: |
A flaw was found in the Linux kernel. When a multi-threaded program sets up a per-thread timer and executes a new program that subsequently fails during startup, the kernel can free timer memory while it remains referenced in an active queue. A local user could exploit this vulnerability to trigger a use-after-free condition, leading to a system crash and Denial of Service (DoS) or potential privilege escalation.
|
Story Points: | --- |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | --- | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
Upstream advisory: https://git.kernel.org/pub/scm/linux/security/vulns.git/plain/cve/published/2026/CVE-2026-98260.mbox This issue has been addressed in the following products: Red Hat Enterprise Linux 10.0 Extended Update Support Via RHSA-2026:83707 https://access.redhat.com/errata/RHSA-2026:83707 This issue has been addressed in the following products: Red Hat Enterprise Linux 9.2 Update Services for SAP Solutions Via RHSA-2026:83739 https://access.redhat.com/errata/RHSA-2026:83739 This issue has been addressed in the following products: Red Hat Enterprise Linux 9.2 Update Services for SAP Solutions Via RHSA-2026:83738 https://access.redhat.com/errata/RHSA-2026:83738 This issue has been addressed in the following products: Red Hat Enterprise Linux 9.6 Extended Update Support Via RHSA-2026:83775 https://access.redhat.com/errata/RHSA-2026:83775 This issue has been addressed in the following products: Red Hat Enterprise Linux 9.4 Update Services for SAP Solutions Via RHSA-2026:83797 https://access.redhat.com/errata/RHSA-2026:83797 A public local privilege escalation exploit has been reported for CVE-2026-98260 (POSIX CPU timer use-after-free). The researcher reports successful root privilege escalation on Linux and Android. PoC and technical details: https://github.com/V4bel/InfinityCore Could Red Hat please confirm the affected status and fix availability for RHEL 8, 9, and 10, including kernel-rt where applicable? Given the reported working exploit, please also consider whether the severity assessment requires an update. Best regards, Akiyoshi Kurita Fedora / EPEL / AlmaLinux Contributor Linux Kernel Developer |
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() ]