FAILED: patch "[PATCH] svcrdma: Reject inline replies that overflow the pull-up" failed to apply to 5.10-stable tree
Subsystems (4)
[email protected]
maintainerThe 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 <[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-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 0fbe20dfe74b783d255bf389a6ea77aa25dc7860
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --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 <[email protected]>
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.
net/sunrpc/xprtrdma/svc_rdma_sendto.c +32 -15
@@ -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;
Sasha Levin
maintainerPATCH 1/1 svcrdma: Reject inline replies that overflow the pull-up buffer
From: Chuck Lever <[email protected]>
[ 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.
--- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 45 ++++++++++++++++++++------- 1 file changed, 33 insertions(+), 12 deletions(-)
net/sunrpc/xprtrdma/svc_rdma_sendto.c +33 -12
@@ -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:
Signature · 1 line
2.53.0