* FAILED: patch "[PATCH] svcrdma: Reject inline replies that overflow the pull-up" failed to apply to 5.10-stable tree
@ 2026-09-03 14:10 gregkh
2026-09-09 9:26 ` [PATCH 5.10.y] svcrdma: Reject inline replies that overflow the pull-up buffer Sasha Levin
0 siblings, 1 reply; 2+ messages in thread
From: gregkh @ 2026-09-03 14:10 UTC (permalink / raw)
To: cel, clm; +Cc: stable
The patch below does not apply to the 5.10-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 <stable@vger.kernel.org>.
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-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 0fbe20dfe74b783d255bf389a6ea77aa25dc7860
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090319-encroach-prepaid-8387@gregkh' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 0fbe20dfe74b783d255bf389a6ea77aa25dc7860 Mon Sep 17 00:00:00 2001
From: Chuck Lever <cel@kernel.org>
Date: Mon, 22 Jun 2026 21:47:28 -0400
Subject: [PATCH] svcrdma: Reject inline replies that overflow the pull-up
buffer
An RPC-over-RDMA client can request a reply, such as an NFS READ
payload, without providing a Write list or a Reply chunk to carry
it. When such a reply needs more scatter/gather entries than the
device's Send Queue supports, svc_rdma_pull_up_needed() selects
pull-up and svc_rdma_pull_up_reply_msg() linearizes the whole
reply into sctxt->sc_xprt_buf. That buffer is only sc_max_req_size
bytes, while the reply on this path is bounded only by the client's
request, so svc_rdma_xb_linearize() copies past the end of the
buffer and corrupts adjacent slab memory. The oversized length is
then stored in sc_sges[0].length and posted, so the device also
reads beyond the mapped region.
The SGE-exhaustion branch is the only pull-up path that can exceed
the buffer: the threshold branch pulls up only replies smaller
than RPCRDMA_PULLUP_THRESH, and replies that fit the device's SGE
budget are sent directly without linearization. Make
svc_rdma_pull_up_needed() report -E2BIG when the reply it would
pull up cannot fit sc_max_req_size, and fail the request with
ERR_CHUNK as RFC 8166 Section 4.5.3 directs rather than dropping
the connection.
The helper no longer answers a simple yes/no question: it now
reports pull-up, no pull-up, or -E2BIG for a reply too large to
linearize. Rename svc_rdma_pull_up_needed() to
svc_rdma_check_pull_up() so its name no longer implies a boolean
predicate.
Fixes: e248aa7be86e ("svcrdma: Remove max_sge check at connect time")
Cc: stable@vger.kernel.org
Reported-by: Chris Mason <clm@meta.com>
Assisted-by: kres:claude-opus-4-7
Link: https://patch.msgid.link/20260623014728.826032-1-cel@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index 7f6d17bf8c1f..c09659b17351 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -825,20 +825,21 @@ static int svc_rdma_xb_count_sges(const struct xdr_buf *xdr,
}
/**
- * svc_rdma_pull_up_needed - Determine whether to use pull-up
+ * svc_rdma_check_pull_up - Determine whether to use pull-up
* @rdma: controlling transport
* @sctxt: send_ctxt for the Send WR
* @write_pcl: Write chunk list provided by client
* @xdr: xdr_buf containing RPC message to transmit
*
* Returns:
- * %true if pull-up must be used
- * %false otherwise
+ * %1 if pull-up must be used
+ * %0 if pull-up is not needed
+ * %-E2BIG if the reply is too large to be pulled up
*/
-static bool svc_rdma_pull_up_needed(const struct svcxprt_rdma *rdma,
- const struct svc_rdma_send_ctxt *sctxt,
- const struct svc_rdma_pcl *write_pcl,
- const struct xdr_buf *xdr)
+static int svc_rdma_check_pull_up(const struct svcxprt_rdma *rdma,
+ const struct svc_rdma_send_ctxt *sctxt,
+ const struct svc_rdma_pcl *write_pcl,
+ const struct xdr_buf *xdr)
{
/* Resources needed for the transport header */
struct svc_rdma_pullup_data args = {
@@ -850,11 +851,22 @@ static bool svc_rdma_pull_up_needed(const struct svcxprt_rdma *rdma,
ret = pcl_process_nonpayloads(write_pcl, xdr,
svc_rdma_xb_count_sges, &args);
if (ret < 0)
- return false;
+ return 0;
if (args.pd_length < RPCRDMA_PULLUP_THRESH)
- return true;
- return args.pd_num_sges >= rdma->sc_max_send_sges;
+ return 1;
+ if (args.pd_num_sges < rdma->sc_max_send_sges)
+ return 0;
+
+ /*
+ * The reply has too many SGEs to Send inline, so it has to be
+ * linearized into sc_xprt_buf. That buffer holds only
+ * sc_max_req_size bytes, so a larger reply cannot be pulled up.
+ * RFC 8166 Section 4.5.3 requires responding with ERR_CHUNK.
+ */
+ if (args.pd_length > rdma->sc_max_req_size)
+ return -E2BIG;
+ return 1;
}
/**
@@ -910,7 +922,7 @@ static int svc_rdma_xb_linearize(const struct xdr_buf *xdr,
* Assemble the elements of @xdr into the transport header buffer.
*
* Assumptions:
- * pull_up_needed has determined that @xdr will fit in the buffer.
+ * check_pull_up has determined that @xdr will fit in the buffer.
*
* Returns:
* %0 if pull-up was successful
@@ -945,6 +957,7 @@ static int svc_rdma_pull_up_reply_msg(const struct svcxprt_rdma *rdma,
*
* Returns:
* %0 if DMA mapping was successful.
+ * %-E2BIG if the reply is too large to be pulled up
* %-EMSGSIZE if a buffer manipulation problem occurred
* %-EIO if DMA mapping failed
*
@@ -960,6 +973,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
.md_rdma = rdma,
.md_ctxt = sctxt,
};
+ int ret;
/* Set up the (persistently-mapped) transport header SGE. */
sctxt->sc_send_wr.num_sge = 1;
@@ -974,7 +988,10 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
/* For pull-up, svc_rdma_send() will sync the transport header.
* No additional DMA mapping is necessary.
*/
- if (svc_rdma_pull_up_needed(rdma, sctxt, write_pcl, xdr))
+ ret = svc_rdma_check_pull_up(rdma, sctxt, write_pcl, xdr);
+ if (ret < 0)
+ return ret;
+ if (ret)
return svc_rdma_pull_up_reply_msg(rdma, sctxt, write_pcl, xdr);
return pcl_process_nonpayloads(write_pcl, xdr,
@@ -1162,7 +1179,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
&rctxt->rc_reply_pcl, sctxt,
&rqstp->rq_res);
if (ret < 0)
- goto reply_chunk;
+ goto send_err;
rc_size = ret;
}
@@ -1183,10 +1200,10 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
ret = svc_rdma_send_reply_msg(rdma, sctxt, rctxt, rqstp);
if (ret < 0)
- goto put_ctxt;
+ goto send_err;
return 0;
-reply_chunk:
+send_err:
if (ret != -E2BIG && ret != -EINVAL)
goto put_ctxt;
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH 5.10.y] svcrdma: Reject inline replies that overflow the pull-up buffer
2026-09-03 14:10 FAILED: patch "[PATCH] svcrdma: Reject inline replies that overflow the pull-up" failed to apply to 5.10-stable tree gregkh
@ 2026-09-09 9:26 ` Sasha Levin
0 siblings, 0 replies; 2+ messages in thread
From: Sasha Levin @ 2026-09-09 9:26 UTC (permalink / raw)
To: stable; +Cc: Chuck Lever, Chris Mason, Sasha Levin
From: Chuck Lever <cel@kernel.org>
[ Upstream commit 0fbe20dfe74b783d255bf389a6ea77aa25dc7860 ]
An RPC-over-RDMA client can request a reply, such as an NFS READ
payload, without providing a Write list or a Reply chunk to carry
it. When such a reply needs more scatter/gather entries than the
device's Send Queue supports, svc_rdma_pull_up_needed() selects
pull-up and svc_rdma_pull_up_reply_msg() linearizes the whole
reply into sctxt->sc_xprt_buf. That buffer is only sc_max_req_size
bytes, while the reply on this path is bounded only by the client's
request, so svc_rdma_xb_linearize() copies past the end of the
buffer and corrupts adjacent slab memory. The oversized length is
then stored in sc_sges[0].length and posted, so the device also
reads beyond the mapped region.
The SGE-exhaustion branch is the only pull-up path that can exceed
the buffer: the threshold branch pulls up only replies smaller
than RPCRDMA_PULLUP_THRESH, and replies that fit the device's SGE
budget are sent directly without linearization. Make
svc_rdma_pull_up_needed() report -E2BIG when the reply it would
pull up cannot fit sc_max_req_size, and fail the request with
ERR_CHUNK as RFC 8166 Section 4.5.3 directs rather than dropping
the connection.
The helper no longer answers a simple yes/no question: it now
reports pull-up, no pull-up, or -E2BIG for a reply too large to
linearize. Rename svc_rdma_pull_up_needed() to
svc_rdma_check_pull_up() so its name no longer implies a boolean
predicate.
Fixes: e248aa7be86e ("svcrdma: Remove max_sge check at connect time")
Cc: stable@vger.kernel.org
Reported-by: Chris Mason <clm@meta.com>
Assisted-by: kres:claude-opus-4-7
Link: https://patch.msgid.link/20260623014728.826032-1-cel@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
[ adapted the pull-up check to Linux 5.10’s direct segment-counting implementation ]
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/sunrpc/xprtrdma/svc_rdma_sendto.c | 45 ++++++++++++++++++++-------
1 file changed, 33 insertions(+), 12 deletions(-)
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index d6436c13d5c47..d272ca1b62141 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -541,27 +541,28 @@ static int svc_rdma_dma_map_buf(struct svcxprt_rdma *rdma,
}
/**
- * svc_rdma_pull_up_needed - Determine whether to use pull-up
+ * svc_rdma_check_pull_up - Determine whether to use pull-up
* @rdma: controlling transport
* @sctxt: send_ctxt for the Send WR
* @rctxt: Write and Reply chunks provided by client
* @xdr: xdr_buf containing RPC message to transmit
*
* Returns:
- * %true if pull-up must be used
- * %false otherwise
+ * %1 if pull-up must be used
+ * %0 if pull-up is not needed
+ * %-E2BIG if the reply is too large to be pulled up
*/
-static bool svc_rdma_pull_up_needed(struct svcxprt_rdma *rdma,
- struct svc_rdma_send_ctxt *sctxt,
- const struct svc_rdma_recv_ctxt *rctxt,
- struct xdr_buf *xdr)
+static int svc_rdma_check_pull_up(struct svcxprt_rdma *rdma,
+ struct svc_rdma_send_ctxt *sctxt,
+ const struct svc_rdma_recv_ctxt *rctxt,
+ struct xdr_buf *xdr)
{
int elements;
/* For small messages, copying bytes is cheaper than DMA mapping.
*/
if (sctxt->sc_hdrbuf.len + xdr->len < RPCRDMA_PULLUP_THRESH)
- return true;
+ return 1;
/* Check whether the xdr_buf has more elements than can
* fit in a single RDMA Send.
@@ -589,7 +590,18 @@ static bool svc_rdma_pull_up_needed(struct svcxprt_rdma *rdma,
++elements;
/* assume 1 SGE is needed for the transport header */
- return elements >= rdma->sc_max_send_sges;
+ if (elements < rdma->sc_max_send_sges)
+ return 0;
+
+ /*
+ * The reply has too many SGEs to Send inline, so it has to be
+ * linearized into sc_xprt_buf. That buffer holds only
+ * sc_max_req_size bytes, so a larger reply cannot be pulled up.
+ * RFC 8166 Section 4.5.3 requires responding with ERR_CHUNK.
+ */
+ if (sctxt->sc_hdrbuf.len + xdr->len > rdma->sc_max_req_size)
+ return -E2BIG;
+ return 1;
}
/**
@@ -602,6 +614,9 @@ static bool svc_rdma_pull_up_needed(struct svcxprt_rdma *rdma,
* The device is not capable of sending the reply directly.
* Assemble the elements of @xdr into the transport header buffer.
*
+ * Assumptions:
+ * check_pull_up has determined that @xdr will fit in the buffer.
+ *
* Returns zero on success, or a negative errno on failure.
*/
static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma,
@@ -662,7 +677,10 @@ static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma,
* Load the xdr_buf into the ctxt's sge array, and DMA map each
* element as it is added. The Send WR's num_sge field is set.
*
- * Returns zero on success, or a negative errno on failure.
+ * Returns:
+ * %0 if DMA mapping was successful.
+ * %-E2BIG if the reply is too large to be pulled up
+ * %-EIO if DMA mapping failed
*/
int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
struct svc_rdma_send_ctxt *sctxt,
@@ -689,7 +707,10 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
/* For pull-up, svc_rdma_send() will sync the transport header.
* No additional DMA mapping is necessary.
*/
- if (svc_rdma_pull_up_needed(rdma, sctxt, rctxt, xdr))
+ ret = svc_rdma_check_pull_up(rdma, sctxt, rctxt, xdr);
+ if (ret < 0)
+ return ret;
+ if (ret)
return svc_rdma_pull_up_reply_msg(rdma, sctxt, rctxt, xdr);
++sctxt->sc_cur_sge_no;
@@ -946,7 +967,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
ret = svc_rdma_send_reply_msg(rdma, sctxt, rctxt, rqstp);
if (ret < 0)
- goto err1;
+ goto err2;
return 0;
err2:
--
2.53.0
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-09-09 9:26 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-03 14:10 FAILED: patch "[PATCH] svcrdma: Reject inline replies that overflow the pull-up" failed to apply to 5.10-stable tree gregkh
2026-09-09 9:26 ` [PATCH 5.10.y] svcrdma: Reject inline replies that overflow the pull-up buffer Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.