CVE-2026-99254 in Linuxinfo

Summary

by MITRE • 11/03/2026

In the Linux kernel, the following vulnerability has been resolved:

io_uring: don't flood a cancelling task with task_work

io_ring_exit_work() asks each task which has used the ring to remove its tctx node, by task_work, and repeats that until the list is empty. io_tctx_exit_cb() doesn't touch the node while the task is in io_uring_cancel_generic(), which removes all the nodes at its end. So the work item queues the callback again as soon as it has completed, for nothing.

That is more than a waste of time. task_work_run() only returns when it finds the list empty. If the rings are released from inside the cancellation, because requests of other rings held the last references to their files, up to 64 work items keep sending callbacks to the one task which is running them. It never finds the list empty, never gets back to the cancellation, the nodes stay, and so it goes on: a task with 60 pairs of rings which poll each other ran 280000 callbacks in 5 seconds, 20 seconds after exit_group(). It ends when all the senders happen to be late at the same time. Until then the task keeps a CPU and the work items busy.

An exiting task can't be killed meanwhile. execve() cancels the requests in the same way, so a live task can get stuck there as well, for minutes. If it takes more than five, the work items run into the WARN_ON_ONCE(time_after(jiffies, timeout)) of io_ring_exit_work(). No privilege is needed for any of this.

If the callback has met a task in cancellation, wait a little before it is sent again. Nobody has to wake the work item up for that: either the node is gone by then, or it is the turn of the next round.

If you want to get best quality of vulnerability data, you may have to visit VulDB.

Analysis

by VulDB Data Team • 11/04/2026

The Linux kernel io_uring subsystem contains a logic flaw within its exit and cleanup routines that leads to severe performance degradation and potential denial-of-service conditions. Specifically, the vulnerability resides in how task work items are queued for cancellation when an io_uring instance is being released. The function io_ring_exit_work iterates through tasks associated with ring contexts to remove their tctx nodes using task_work mechanisms. However, there is a race condition where io_tctx_exit_cb does not properly account for the state of the node while the target task is already inside io_uring_cancel_generic. This routine removes all relevant nodes at its conclusion, meaning that if the callback executes during this window, it queues another identical work item unnecessarily because the underlying data structure has effectively been cleared or is in a transitional state where further processing yields no progress.

This inefficiency escalates into a significant operational impact when multiple rings are involved and hold references to each other's file descriptors. In such scenarios, up to sixty concurrent work items can continuously send callbacks to a single exiting task without ever detecting that the list of pending tasks is effectively empty for practical purposes. The function task_work_run only returns once it confirms an empty list, but due to this feedback loop, the condition is never met during active cancellation. Consequently, a task attempting to exit or execute a new binary via execve can become stuck in an infinite-like loop of processing these redundant callbacks. Real-world testing has demonstrated that tasks with numerous ring pairs polling each other can generate hundreds of thousands of callbacks within seconds, consuming CPU resources for extended periods even after the process group should have terminated.

The security implications are classified under CWE-835 as a Loop with Unreachable Exit Condition, leading to resource exhaustion and denial-of-service. An unprivileged local user can exploit this flaw by creating multiple io_uring instances that reference each other's files and then triggering their cancellation or exit. This causes the affected task to remain busy for minutes, preventing it from terminating properly. If the execution time exceeds five seconds, the kernel triggers a WARN_ON_ONCE warning due to timeout violations in io_ring_exit_work, but the process remains unkillable until the scheduler eventually allows all conflicting senders to pause simultaneously. This behavior effectively locks up system resources and can impact other processes on the host by monopolizing CPU cycles and preventing clean task termination.

To mitigate this vulnerability, developers implemented a logic change where callbacks that encounter a task currently in cancellation are delayed before being resent again. Instead of immediately re-queuing the work item, which perpetuates the loop, the system waits for a brief interval or allows the next scheduling round to occur. This ensures that either the node has been removed by the time the callback runs, or it is simply not yet due for processing in the current cycle. This adjustment breaks the infinite feedback loop and allows task_work_run to correctly identify when all work items have completed, enabling the cancellation process to finish normally. System administrators should apply kernel updates that include this patch to restore normal exit behavior and prevent local denial-of-service attacks via io_uring resource manipulation.

Responsible

Linux

Reservation

09/25/2026

Disclosure

11/03/2026

Moderation

accepted

EPSS

0.00000

KEV

no

Activities

low

Sources

Are you interested in using VulDB?

Download the whitepaper to learn more about our service!