---
id: "CVE-2026-99243"
kind: "vulnerability"
aliases: ["CVE-2026-99243"]
title: "Linux kernel: io_uring worker exit can hang on weakly ordered CPUs"
severity: "unknown"
cvss: null
epss: null
exploited: false
status: "open"
category: "other"
products: []
ecosystems: []
tags: ["io_uring", "linux-kernel", "other", "self-hosted"]
not_affected_if: ["kernel-without-io_uring"]
published_at: "2026-11-03T12:17:30+00:00"
first_seen_at: "2026-11-03T12:20:38+00:00"
updated_at: "2026-11-03T12:23:04+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-99243", "first_seen_at": "2026-11-03T12:20:38+00:00"}]
---

# Linux kernel: io_uring worker exit can hang on weakly ordered CPUs

A memory-ordering bug in the Linux kernel's io_uring worker cleanup can leave an exiting task waiting forever on a worker that never finishes. The sources describe a hang (denial of service), not code execution or data theft.

_Summary, check and fix written by a model from the sources; labelled as such._

## Timeline

- 2026-11-03T12:20:38+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-99243

## From the sources

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

io-wq: order the exit bit against worker creation task work

io_wq_exit_workers() cancels task work for queued worker creation with
task_work_cancel_match(). That has a plain load of task->task_works.

io_queue_worker_create() adds the new entry and tests IO_WQ_BIT_EXIT to
cancel it if the workqueue is already on its way out.

That must be ordered. task_work_add() has a full barrier via cmpxchg().
But io_wq_exit_start() sets the bit with set_bit() which doesn't have
any memory ordering.

So afaict, on weakly ordered architectures the exiting task may load
task_works before the store of the bit is visible. The other side tests
the bit before the store is visible as well. So the entry remains queued
with worker_refs and the exiting task waits on worker_done indefinitely.

If the task still has rings then io_uring_del_tctx_node() provides the
barrier via test_and_set_bit() in io_wq_set_exit_on_idle(). When it
has closed all rings though that barrier is gone.

Add the barrier after the set_bit().

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
