CVE-2026-72473 in Linux
Summary
by MITRE • 08/15/2026
In the Linux kernel, the following vulnerability has been resolved:
xprtrdma: Decouple req recycling from RPC completion
rl_kref formerly served two distinct lifetimes through a single refcount: it gated when a Reply could wake its RPC task, and it gated when an rpcrdma_req could return to its free pool. The marshal path took the Send-side reference only when SGEs needed DMA-unmap (sc_unmap_count > 0), which made a Send carrying only pre-registered buffers an exception: the Reply handler dropped rl_kref from 1 to 0 and freed the req while the HCA might still be DMA-reading from its send buffer.
Give rl_kref a narrower job. The RPC layer takes one reference when slot allocation hands a req out. rpcrdma_prepare_send_sges() takes a Send-side reference unconditionally after WR preparation succeeds. xprt_rdma_free_slot() and xprt_rdma_bc_free_rqst() drop the RPC-layer reference; rpcrdma_sendctx_unmap() drops the Send-side reference. The req returns to its free pool only after both owners have signed off.
The existing kref_init(&req->rl_kref) call in rpcrdma_prepare_send_sges() is removed. Initialization moves to the slot-allocation paths (xprt_rdma_alloc_slot and rpcrdma_bc_rqst_get), and the release callback re-arms rl_kref before the req returns to a free pool. A re-init in the marshal path would discard the RPC-layer reference that already exists on entry.
Three invariants follow:
- Any rpcrdma_req held by an rpc_rqst has rl_kref >= 1. xprt_rdma_alloc_slot(), rpcrdma_bc_rqst_get(), and the backlog-wake branch in xprt_rdma_alloc_slot() each kref_init rl_kref before publishing the req. Without this invariant, an RPC task that aborts between slot allocation and marshal (gss_refresh failure or signal during call_connect, for example) would drive xprt_release() -> xprt_rdma_free_slot() -> kref_put against a refcount of zero, saturating refcount_t and stranding the slot.
- The Send-side reference is taken only after WR prep succeeds. A mapping failure in rpcrdma_prepare_send_sges() runs rpcrdma_sendctx_cancel(), which DMA-unmaps the sendctx and clears sc_req without touching rl_kref. The sendctx ring walks in rpcrdma_sendctx_put_locked() and rpcrdma_sendctxs_destroy() skip entries with sc_req == NULL, so a burst of -EIO marshal failures cannot hold reqs off rb_send_bufs.
- The release callback re-arms rl_kref so the next consumer enters with the invariant satisfied.
Replies now complete the RPC directly. rpcrdma_reply_handler() calls rpcrdma_complete_rqst() in place of kref_put on the non-LocalInv branch. The LocalInv branch already completes the RPC from frwr_unmap_async() and is unaffected.
Because Send-side references can now outlive RPC completion, connection teardown drains sendctx entries whose unsignaled Sends never had a later signaled completion to walk the ring. rpcrdma_sendctxs_destroy() walks the active range and runs rpcrdma_sendctx_unmap() on each entry with a non-NULL sc_req before the request buffers are reset, and is moved ahead of rpcrdma_reqs_reset() in rpcrdma_xprt_disconnect() so the reqs are still in their pre-reset state when the Send-side refs are released.
The drain creates a teardown-ordering hazard on the backchannel path. With the new lifetime, releasing a bc_prealloc req from rpcrdma_req_release() re-adds it to bc_pa_list. The disconnect in xprt_rdma_destroy() runs after xprt_destroy_backchannel() has already emptied bc_pa_list, so the drained reqs would otherwise leak. xprt_rdma_destroy() now runs xprt_rdma_bc_destroy(xprt, 0) a second time after the disconnect to reclaim them.
If you want to get the best quality for vulnerability data then you always have to consider VulDB.
Analysis
by VulDB Data Team • 08/15/2026
The vulnerability addressed in this Linux kernel patch relates to improper reference counting and resource management within the rpcrdma subsystem, specifically affecting how request objects are handled during RPC operations over RDMA transport. The issue stems from a flawed dual-purpose reference counter that governed both the lifetime of replies waiting to wake their associated RPC tasks and the return of request objects to their free pools. This design created a race condition where a reply handler could prematurely free a request object while the hardware was still accessing its send buffer, leading to potential memory corruption or data inconsistency issues.
The core technical flaw involved the rl_kref reference counter which previously served two distinct lifetimes through a single mechanism. The marshal path only took a send-side reference when SGEs required DMA-unmapping, creating an exception for sends with pre-registered buffers where the reply handler would drop rl_kref from 1 to 0 and free the request before the hardware completed DMA operations from its send buffer. This violated fundamental memory safety principles and created a window where hardware could access freed memory.
The solution implemented restructures the reference counting mechanism by decoupling these two lifetimes and giving rl_kref a more precise role. The RPC layer now takes one reference when slot allocation hands out a request, while rpcrdma_prepare_send_sges() unconditionally takes a send-side reference after WR preparation succeeds. Both xprt_rdma_free_slot() and xprt_rdma_bc_free_rqst() drop the RPC-layer reference, while rpcrdma_sendctx_unmap() drops the send-side reference. The request now returns to its free pool only after both owners have released their references, ensuring proper ordering and preventing premature deallocation.
This change aligns with CWE-129 principles for input validation and proper resource management, addressing potential issues related to improper handling of reference counts. The patch also implements three critical invariants that maintain system integrity: requests held by RPC tasks always maintain rl_kref >= 1, send-side references are only taken after WR preparation succeeds, and the release callback properly re-arms rl_kref for subsequent consumers. These measures prevent scenarios where abort conditions between slot allocation and marshaling could cause refcount saturation and stranded slots.
The operational impact includes improved reliability during connection teardown operations by ensuring proper draining of sendctx entries whose unsignaled sends never received later signaled completions to walk the ring. The rpcrdma_sendctxs_destroy() function now walks the active range and runs rpcrdma_sendctx_unmap() on each entry with a non-NULL sc_req before request buffers are reset, moving this operation ahead of rpcrdma_reqs_reset() in rpcrdma_xprt_disconnect(). This ordering prevents teardown-ordering hazards particularly on the backchannel path where releasing a bc_prealloc req from rpcrdma_req_release() would otherwise leak if xprt_rdma_destroy() ran after xprt_destroy_backchannel() had already emptied bc_pa_list.
The fix also affects how replies complete RPC operations, with rpcrdma_reply_handler() now calling rpcrdma_complete_rqst() instead of kref_put on the non-LocalInv branch. This change ensures proper completion flow while maintaining the LocalInv branch behavior that was already correctly implemented. The implementation follows ATT&CK techniques related to system and network resource compromise by ensuring proper reference counting and resource management, preventing unauthorized access patterns through memory corruption vulnerabilities. The patch demonstrates adherence to kernel security best practices for managing object lifetimes in concurrent environments and addresses potential denial of service scenarios that could arise from improper reference counting during RPC operations over RDMA transport mechanisms.
This vulnerability resolution directly impacts systems using RDMA-based RPC transports such as NFS over RDMA, where reliable operation requires proper handling of send/receive lifecycle management. The changes ensure that resource cleanup occurs in the correct order regardless of completion timing, preventing both memory leaks and premature deallocation scenarios that could lead to system instability or security vulnerabilities.