FAILED: patch "[PATCH] svcrdma: Reject Read lists that exceed the page budget" failed to apply to 6.18-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 0ca487abb3bdf581851664b5db21f364caf57682
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090330-audacity-nutcase-5491@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0ca487abb3bdf581851664b5db21f364caf57682 Mon Sep 17 00:00:00 2001
From: Chuck Lever <[email protected]>
Date: Tue, 26 May 2026 13:34:54 -0400
Subject: [PATCH] svcrdma: Reject Read lists that exceed the page budget
Individual Read segment lengths are validated at decode time, but nothing prevents a requester from sending multiple segments whose cumulative length exceeds the rq_pages array budget. When one segment fills the page array exactly, the runtime guard in svc_rdma_build_read_segment() is bypassed because len reaches zero. A subsequent segment then accesses the NULL sentinel slot at rq_pages[rq_maxpages], resulting in a NULL pointer dereference during DMA mapping.
Accumulate pages across all Read segments and reject the message at decode time when the total would overflow the page budget.
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +9 -3
@@ -440,11 +440,14 @@ static void svc_rdma_build_arg_xdr(struct svc_rqst *rqstp,* to the first byte past the Read list. rc_read_pcl and * rc_call_pcl cl_count fields are set to the number of * Read segments in the list. -* %false: Read list is corrupt. @rctxt's xdr_stream is left in an -* unknown state. +* %false: Read list is corrupt or exceeds the page budget. @rctxt's +* xdr_stream is left in an unknown state. */ static bool xdr_count_read_segments (struct svc_rdma_recv_ctxt *rctxt,__be32 *p) { +unsigned int maxlen = rctxt->rc_maxpages <<PAGE_SHIFT ; +unsigned int total_len =0 ; + rctxt->rc_call_pcl.cl_count =0 ; rctxt->rc_read_pcl.cl_count =0 ;while (xdr_item_is_present (p)) {
@@ -458,7 +461,10 @@ static bool xdr_count_read_segments(struct svc_rdma_recv_ctxt *rctxt, __be32 *p)xdr_decode_read_segment (p, &position, &handle, &length, &offset); -if (length > rctxt->rc_maxpages <<PAGE_SHIFT ) +if (length > maxlen) +return false; + total_len += length; +if (PAGE_ALIGN (total_len) > maxlen)return false;if (position) {if (position &3 )
Sasha Levin
maintainerPATCH 1/2 svcrdma: Reject oversized Read segments at decode time
From: Chuck Lever <[email protected]>
[ Upstream commit af6f0e06bed818ee7fc8b869915964410020a1c5 ]
The RPC/RDMA Read list decoder stores wire-supplied segment lengths without validation. xdr_count_read_segments() checks 4-byte alignment for non-zero position values but does not cap the segment length.
An oversized rs_length reaches svc_rdma_build_read_segment(), which derives nr_bvec from it and can drive a large dynamic bvec allocation before verifying that enough rq_pages remain. If the post-allocation page-overrun guard fires, the freshly acquired rw context is not returned, leaking the resource.
Reject any segment whose length exceeds the receive context's page budget during Read list decoding, consistent with how xdr_check_write_chunk() bounds Write segment counts against rc_maxpages. Also return the rw context on the existing post-allocation overrun path in svc_rdma_build_read_segment(), keeping that defensive guard balanced.
Stable-dep-of: 0ca487abb3bd ("svcrdma: Reject Read lists that exceed the page budget")
--- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 2 ++ net/sunrpc/xprtrdma/svc_rdma_rw.c | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +2 -0
@@ -448,6 +448,8 @@ static bool xdr_count_read_segments(struct svc_rdma_recv_ctxt *rctxt, __be32 *p)xdr_decode_read_segment (p, &position, &handle, &length, &offset); +if (length > rctxt->rc_maxpages <<PAGE_SHIFT ) +return false;if (position) {if (position &3 )return false;
net/sunrpc/xprtrdma/svc_rdma_rw.c +3 -2
@@ -766,7 +766,7 @@ static int svc_rdma_build_read_segment(struct svc_rqst *rqstp, len -= seg_len;if (len && ((head->rc_curpage +1 ) > rqstp->rq_maxpages)) - goto out_overrun; + goto out_put; } ret = svc_rdma_rw_ctx_init(rdma, ctxt, segment->rs_offset,
@@ -779,7 +779,8 @@ static int svc_rdma_build_read_segment(struct svc_rqst *rqstp, cc->cc_sqecount += ret;return 0 ; -out_overrun: +out_put: +svc_rdma_put_rw_ctxt (rdma, ctxt);trace_svcrdma_page_overrun_err (&cc->cc_cid, head->rc_curpage);return -EINVAL ; }
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 svcrdma: Reject Read lists that exceed the page budget
From: Chuck Lever <[email protected]>
[ Upstream commit 0ca487abb3bdf581851664b5db21f364caf57682 ]
Individual Read segment lengths are validated at decode time, but nothing prevents a requester from sending multiple segments whose cumulative length exceeds the rq_pages array budget. When one segment fills the page array exactly, the runtime guard in svc_rdma_build_read_segment() is bypassed because len reaches zero. A subsequent segment then accesses the NULL sentinel slot at rq_pages[rq_maxpages], resulting in a NULL pointer dereference during DMA mapping.
Accumulate pages across all Read segments and reject the message at decode time when the total would overflow the page budget.
--- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +9 -3
@@ -430,11 +430,14 @@ static void svc_rdma_build_arg_xdr(struct svc_rqst *rqstp,* to the first byte past the Read list. rc_read_pcl and * rc_call_pcl cl_count fields are set to the number of * Read segments in the list. -* %false: Read list is corrupt. @rctxt's xdr_stream is left in an -* unknown state. +* %false: Read list is corrupt or exceeds the page budget. @rctxt's +* xdr_stream is left in an unknown state. */ static bool xdr_count_read_segments (struct svc_rdma_recv_ctxt *rctxt,__be32 *p) { +unsigned int maxlen = rctxt->rc_maxpages <<PAGE_SHIFT ; +unsigned int total_len =0 ; + rctxt->rc_call_pcl.cl_count =0 ; rctxt->rc_read_pcl.cl_count =0 ;while (xdr_item_is_present (p)) {
@@ -448,7 +451,10 @@ static bool xdr_count_read_segments(struct svc_rdma_recv_ctxt *rctxt, __be32 *p)xdr_decode_read_segment (p, &position, &handle, &length, &offset); -if (length > rctxt->rc_maxpages <<PAGE_SHIFT ) +if (length > maxlen) +return false; + total_len += length; +if (PAGE_ALIGN (total_len) > maxlen)return false;if (position) {if (position &3 )
Signature · 1 line
2.53.0