PT-2026-47326 · Linux · Linux
Published
2026-06-08
·
Updated
2026-06-08
·
CVE-2026-46274
None
No severity ratings or metrics are available. When they are, we'll update the corresponding info on the page.
In the Linux kernel, the following vulnerability has been resolved:
io-wq: check that the predecessor is hashed in io wq remove pending()
io wq remove pending() needs to fix up wq->hash tail[] if the cancelled
work was the tail of its hash bucket. When doing this, it checks whether
the preceding entry in acct->work list has the same hash value, but
never checks that the predecessor is hashed at all. io get work hash()
is simply atomic read(&work->flags) >> IO WQ HASH SHIFT, and the hash
bits are never set for non-hashed work, so it returns 0. Thus, when a
hashed bucket-0 work is cancelled while a non-hashed work is its list
predecessor, the check spuriously passes and a pointer to the non-hashed
io kiocb is stored in wq->hash tail[0].
Because non-hashed work is dequeued via the fast path in
io get next work(), which never touches hash tail[], the stale pointer
is never cleared. Therefore, after the non-hashed io kiocb completes and
is freed back to req cachep, wq->hash tail[0] is a dangling pointer. The
io wq is per-task (tctx->io wq) and survives ring open/close, so the
dangling pointer persists for the lifetime of the task; the next hashed
bucket-0 enqueue dereferences it in io wq insert work() and
wq list add after() writes through freed memory.
Add the missing io wq is hashed() check so a non-hashed predecessor
never inherits a hash tail[] slot.
Found an issue in the description? Have something to add? Feel free to write us 👾
Related Identifiers
Affected Products
Linux