FAILED: patch "[PATCH] svcrdma: Reject Write/Reply chunks with segcount 0" failed to apply to 6.12-stable tree
Subsystems (4)
[email protected]
maintainerThe patch below does not apply to the 6.12-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.12.y
git checkout FETCH_HEAD
git cherry-pick -x 9808eb7656666acc7291bae9ab6b987bd16e47e0
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026090342-canary-synopses-a220@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 9808eb7656666acc7291bae9ab6b987bd16e47e0 Mon Sep 17 00:00:00 2001
From: Chris Mason <[email protected]>
Date: Tue, 26 May 2026 09:35:59 -0400
Subject: [PATCH] svcrdma: Reject Write/Reply chunks with segcount 0
A peer can send a Write or Reply chunk whose segcount field is zero. xdr_check_write_chunk() only rejects segcount > rc_maxpages, so zero passes the range check, and xdr_inline_decode(stream, 0) returns the current (non-NULL) cursor without advancing. The function returns true and pcl_alloc_write() then links a struct svc_rdma_chunk with ch_segcount == 0 onto rc_write_pcl or rc_reply_pcl.
An earlier patch in this series made pcl_for_each_segment() safe for ch_segcount == 0, so this no longer drives the memory walk it used to. Rejecting the malformed frame at the decode boundary is still worthwhile as defense in depth: it keeps degenerate zero-segment chunks off the parsed chunk lists entirely, so any future consumer that walks ch_segments directly cannot observe one, and it makes the zero-floor easy to backport to trees where the macro change is more intrusive. RFC 8166 has no meaning for a Write/Reply chunk that describes no remote buffer, so no legitimate client is affected.
xdr_check_reply_chunk() funnels Reply chunks through xdr_check_write_chunk() and inherits the same rejection.
pcl_alloc_write() also links each chunk onto the parsed chunk list before filling its segment array. If a future change weakens the segcount-0 rejection, an incomplete chunk is visible to consumers during the fill loop. Reorder so that list_add_tail() follows the segment fill loop, ensuring only fully-populated chunks appear on the list.
net/sunrpc/xprtrdma/svc_rdma_pcl.c +1 -1
@@ -213,7 +213,6 @@ bool pcl_alloc_write(struct svc_rdma_recv_ctxt *rctxt, chunk =pcl_alloc_chunk (segcount,0 );if (!chunk)return false; -list_add_tail (&chunk->ch_list, &pcl->cl_chunks);for (j =0 ; j < segcount; j++) { segment = &chunk->ch_segments[j];
@@ -225,6 +224,7 @@ bool pcl_alloc_write(struct svc_rdma_recv_ctxt *rctxt, chunk->ch_length += segment->rs_length; chunk->ch_segcount++; } +list_add_tail (&chunk->ch_list, &pcl->cl_chunks); }return true; }
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +6 -3
@@ -510,10 +510,13 @@ static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt)return false;/* Before trusting the segcount value enough to use it in -* a computation, perform a simple range check. This is an -* arbitrary but sensible limit (ie, not architectural). +* a computation, perform a simple range check. A zero +* segcount describes no remote buffer and is rejected so +* downstream consumers never see a degenerate ch_segcount==0 +* chunk. The upper bound is an arbitrary but sensible limit +* (ie, not architectural). */ -if (unlikely (segcount > rctxt->rc_maxpages)) +if (segcount ==0 ||unlikely (segcount > rctxt->rc_maxpages))return false; p = xdr_inline_decode(&rctxt->rc_stream,
Sasha Levin
maintainerPATCH 1/3 sunrpc: Add a helper to derive maxpages from sv_max_mesg
From: Chuck Lever <[email protected]>
[ Upstream commit eff042ddf4b9587fa7394d502b93e06ec6015177 ]
This page count is to be used to allocate various arrays of pages and bio_vecs, replacing the fixed RPCSVC_MAXPAGES value.
The documenting comment is somewhat stale -- of course NFSv4 COMPOUND procedures may have multiple payloads.
Stable-dep-of: 9808eb765666 ("svcrdma: Reject Write/Reply chunks with segcount 0")
--- include/linux/sunrpc/svc.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
include/linux/sunrpc/svc.h +17 -0
@@ -163,6 +163,23 @@ extern u32 svc_max_payload(const struct svc_rqst *rqstp);#define RPCSVC_MAXPAGES ((RPCSVC_MAXPAYLOAD+PAGE_SIZE-1)/PAGE_SIZE \ + 2 + 1) +/** +* svc_serv_maxpages - maximum count of pages needed for one RPC message +* @serv: RPC service context +* +* Returns a count of pages or vectors that can hold the maximum +* size RPC message for @serv. +* +* Each request/reply pair can have at most one "payload", plus two +* pages, one for the request, and one for the reply. +* nfsd_splice_actor() might need an extra page when a READ payload +* is not page-aligned. +*/ +static inline unsigned long svc_serv_maxpages (const struct svc_serv *serv) +{ +return DIV_ROUND_UP (serv->sv_max_mesg,PAGE_SIZE ) +2 +1 ; +} +/* * The context of a single thread, including the request currently being * processed.
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/3 svcrdma: Adjust the number of entries in svc_rdma_recv_ctxt::rc_pages
From: Chuck Lever <[email protected]>
[ Upstream commit 81381d1a90dea186ce4585d9bd3cdc40b50e9c48 ]
Allow allocation of more entries in the rc_pages[] array when the maximum size of an RPC message is increased.
Stable-dep-of: 9808eb765666 ("svcrdma: Reject Write/Reply chunks with segcount 0")
--- include/linux/sunrpc/svc_rdma.h | 3 ++- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 8 ++++++-- 2 files changed, 8 insertions(+), 3 deletions(-)
include/linux/sunrpc/svc_rdma.h +2 -1
@@ -202,7 +202,8 @@ struct svc_rdma_recv_ctxt {struct svc_rdma_pcl rc_reply_pcl;unsigned int rc_page_count; -struct page *rc_pages[RPCSVC_MAXPAGES ]; +unsigned long rc_maxpages; + struct page *rc_pages[] __counted_by(rc_maxpages); };/*
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +6 -2
@@ -120,12 +120,16 @@ svc_rdma_recv_ctxt_alloc(struct svcxprt_rdma *rdma) {int node =ibdev_to_node (rdma->sc_cm_id->device);struct svc_rdma_recv_ctxt *ctxt; +unsigned long pages;dma_addr_t addr;void *buffer; - ctxt =kzalloc_node (sizeof (*ctxt),GFP_KERNEL , node); + pages =svc_serv_maxpages (rdma->sc_xprt.xpt_server); + ctxt =kzalloc_node (struct_size (ctxt, rc_pages, pages), +GFP_KERNEL , node);if (!ctxt) goto fail0; + ctxt->rc_maxpages = pages; buffer =kmalloc_node (rdma->sc_max_req_size,GFP_KERNEL , node);if (!buffer) goto fail1;
@@ -497,7 +501,7 @@ static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt)* a computation, perform a simple range check. This is an * arbitrary but sensible limit (ie, not architectural). */ -if (unlikely (segcount >RPCSVC_MAXPAGES )) +if (unlikely (segcount > rctxt->rc_maxpages))return false; p = xdr_inline_decode(&rctxt->rc_stream,
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 3/3 svcrdma: Reject Write/Reply chunks with segcount 0
In reply to Sasha LevinFrom: Chris Mason <[email protected]>
[ Upstream commit 9808eb7656666acc7291bae9ab6b987bd16e47e0 ]
A peer can send a Write or Reply chunk whose segcount field is zero. xdr_check_write_chunk() only rejects segcount > rc_maxpages, so zero passes the range check, and xdr_inline_decode(stream, 0) returns the current (non-NULL) cursor without advancing. The function returns true and pcl_alloc_write() then links a struct svc_rdma_chunk with ch_segcount == 0 onto rc_write_pcl or rc_reply_pcl.
An earlier patch in this series made pcl_for_each_segment() safe for ch_segcount == 0, so this no longer drives the memory walk it used to. Rejecting the malformed frame at the decode boundary is still worthwhile as defense in depth: it keeps degenerate zero-segment chunks off the parsed chunk lists entirely, so any future consumer that walks ch_segments directly cannot observe one, and it makes the zero-floor easy to backport to trees where the macro change is more intrusive. RFC 8166 has no meaning for a Write/Reply chunk that describes no remote buffer, so no legitimate client is affected.
xdr_check_reply_chunk() funnels Reply chunks through xdr_check_write_chunk() and inherits the same rejection.
pcl_alloc_write() also links each chunk onto the parsed chunk list before filling its segment array. If a future change weakens the segcount-0 rejection, an incomplete chunk is visible to consumers during the fill loop. Reorder so that list_add_tail() follows the segment fill loop, ensuring only fully-populated chunks appear on the list.
--- net/sunrpc/xprtrdma/svc_rdma_pcl.c | 2 +- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_pcl.c +1 -1
@@ -213,7 +213,6 @@ bool pcl_alloc_write(struct svc_rdma_recv_ctxt *rctxt, chunk =pcl_alloc_chunk (segcount,0 );if (!chunk)return false; -list_add_tail (&chunk->ch_list, &pcl->cl_chunks);for (j =0 ; j < segcount; j++) { segment = &chunk->ch_segments[j];
@@ -225,6 +224,7 @@ bool pcl_alloc_write(struct svc_rdma_recv_ctxt *rctxt, chunk->ch_length += segment->rs_length; chunk->ch_segcount++; } +list_add_tail (&chunk->ch_list, &pcl->cl_chunks); }return true; }
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +6 -3
@@ -498,10 +498,13 @@ static bool xdr_check_write_chunk(struct svc_rdma_recv_ctxt *rctxt)return false;/* Before trusting the segcount value enough to use it in -* a computation, perform a simple range check. This is an -* arbitrary but sensible limit (ie, not architectural). +* a computation, perform a simple range check. A zero +* segcount describes no remote buffer and is rejected so +* downstream consumers never see a degenerate ch_segcount==0 +* chunk. The upper bound is an arbitrary but sensible limit +* (ie, not architectural). */ -if (unlikely (segcount > rctxt->rc_maxpages)) +if (segcount ==0 ||unlikely (segcount > rctxt->rc_maxpages))return false; p = xdr_inline_decode(&rctxt->rc_stream,
Signature · 1 line
2.53.0