KernelScan.io

HIGH

blk-mq CachedRequest UAF

CVE-2026-64017

CVSS 7.8 / 10.0 NVD

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H

KernelScan AI7.0HIGH

01

In the Linux kernel, the following vulnerability has been resolved: blk-mq: pop cached request if it is usable When submitting a bio to blk-mq, if the task should sleep after peeking a cached request, but before it pops it, the plug flushes and calls blk_mq_free_plug_rqs, freeing the cached_rqs. This creates a use-after-free bug. Fix this by popping the cached request before any possible blocking calls if it is suitable for use. Popping this request first holds a queue reference, so avoid any serialization races with queue freezes and can safely proceed with dispatching that request to the driver. This potentially increases a timing window from when a driver wants to freeze its queue to when requests stop being dispatched. That scenario is off the fast path though, and drivers need to appropriately handle requests during a freeze request anyway. The downside is the popped element needs to be individually freed when we performed a bio plug merge. The cached request would have had to be freed later anyway, but this patch does it inline with building the plug list instead of after flushing it.

02

Engine v0.4.0

Risk summary

A local unprivileged user submitting I/O can trigger a use-after-free in the block multi-queue layer when a plug flush races with a cached request peek. Successful exploitation could allow an attacker to corrupt kernel heap memory, potentially leading to privilege escalation or a kernel crash. The race window is narrow, requiring specific timing between bio submission and plug flushing.

Affectedblock/blk-mq.c (block multi-queue I/O scheduler)

Vulnerability analysis

The vulnerability is a use-after-free race condition in blk_mq_submit_bio() in block/blk-mq.c. The original code first peeked at a cached request from the plug list (blk_mq_peek_cached_request) without removing it, then later called blk_mq_use_cached_rq() which would pop it and call rq_qos_throttle(). If rq_qos_throttle() blocked between the peek and the pop, the plug could be flushed by another code path (blk_mq_free_plug_rqs), freeing the cached_rqs list. When execution resumed, the code would attempt to use the already-freed request pointer, constituting a use-after-free. The fix renames the function to blk_mq_get_cached_request() and moves the rq_list_pop() call to occur before returning the request — i.e., before any potentially blocking operations. This ensures the request is removed from the plug list before any blocking call can trigger a plug flush. The attack surface is any local process that can perform block I/O (e.g., writing to a disk), which is available to unprivileged users. The race condition requires specific timing (AC:High), but the impact is full heap corruption primitives (C:High, I:High, A:High).

03

BranchIntroducedFixed inPatch commit
6.16.1.726.223d8ea1e303b
6.56.5.136.697e2d08de282
6.18—6.18.45—
7.0—7.0.11—
mainline—7.1—
6.12—6.12.104dc278e9bf2b9
6.66.6.36.7388468f7e7d1