CVE-2026-99228
NoneCVSS
—
EPSS
0.2%
Published
Nov 2, 2026
CISA due date
—
Cloudanix analysis
A Linux kernel bug can make some programs using fast input-output features freeze when they try to close, requiring a manual shutdown to recover.
- Exploitation
- Local Privilege
- Attacker needs
- Local User
- Complexity
- Moderate
- Impact
- Denial Of Service
- Component
- OS kernel
- Class
- Race Condition
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
A race in io_uring/io-wq allows TIF_NOTIFY_SIGNAL to be cleared by io_run_task_work before a bounded work item (such as fifo_open) is started under IO_WQ_BIT_EXIT, so the worker misses the wake from io_wq_worker_wake and blocks indefinitely in an interruptible wait.
Why it matters to the business
Applications or services that use io_uring for asynchronous file operations can hang on thread or process exit, forcing administrators to kill processes, leaking resources and disrupting availability until the system is rebooted or the offending task is terminated.
How an attack unfolds
A local attacker submits an async IORING_OP_OPENAT for a FIFO with no writer, then immediately exits the submitting thread; the exit path signals workers once, but the race lets a worker clear the signal before starting the bounded work, leaving the thread stuck in do_exit.
How to fix it
Apply the upstream kernel commit that sets TIF_NOTIFY_SIGNAL for bounded work started with IO_WQ_BIT_EXIT and uses clear_notify_signal as a barrier; rebuild and reboot with the patched kernel.
How to confirm the fix worked
Inspect io_wq.c for the added IO_WQ_BIT_EXIT handling and clear_notify_signal call before wait_for_completion_timeout; verify that io_assign_current_work no longer drops the signal for exit work items.
Typical attack path
- Create or open a FIFO with no writer end
- Submit IORING_OP_OPENAT via io_uring with IOSQE_ASYNC
- Exit the thread or process that owns the ring
- io_wq_exit_workers signals workers but the signal is lost
- Worker blocks forever in wait_for_partner inside fifo_open
How to detect it
Search kernel logs and process listings for threads stuck in do_exit with io_wq workers blocked on wait_for_completion_timeout or wait_for_partner after an io_uring open; correlate with recent io_uring ring submissions that target FIFOs.
What your security team should do
- Prioritize kernel updates containing the io-wq exit fix
- Temporarily restrict untrusted code from using io_uring open operations on FIFOs or named pipes
- Monitor process exit paths for stuck io_uring workers in production workloads
- Review any custom io_uring usage for similar bounded-work patterns
The record
In the Linux kernel, the following vulnerability has been resolved: io_uring/io-wq: don't lose the signal that ends work When a thread exits, only its tracked requests are cancelled. Then its io-wq is torn down. io_wq_exit_workers() signals every worker, to get it out of an interruptible sleep, and waits for all of them to exit. Before they do, they go through the work that is left. Unbounded work is cancelled. Bounded work is run, as it is expected to end by itself. Not all of it does. An open has no file yet, so it counts as bounded, and the open of a FIFO waits for the other end. That is what the signal is for. But the workers are signalled once, and a worker that hasn't started the work by then loses the signal: io_wq_exit_workers() io_worker_handle_work() io_wq_worker_wake() set TIF_NOTIFY_SIGNAL io_assign_current_work() io_run_task_work() clear TIF_NOTIFY_SIGNAL io_wq_submit_work() fifo_open() wait_for_partner() wait_for_completion_timeout() The thread never gets out of do_exit(): IORING_OP_OPENAT of a FIFO without a writer, IOSQE_ASYNC exit of the thread that has submitted it hangs in more than 9 of 10 attempts (4 CPUs, KVM), until the process is killed. Set TIF_NOTIFY_SIGNAL for bounded work that is started with IO_WQ_BIT_EXIT set. The bit is set before the workers are signalled, and it is tested after the flag has been cleared, with clear_notify_signal() providing the barrier. So either the flag stays, or the bit is seen. Work that is started while the io-wq exits is treated like work that is being run at that time: it isn't interrupted unless it waits interruptibly.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|