From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A150F19CD0A for ; Wed, 9 Sep 2026 00:36:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788914192; cv=none; b=UO1shHa2oC++kjbhox/WPE9jNCC0pZ/OKumJt6qnErBszx15P4Azq/oqBhvHzmu9L5mwOqH1kzCGhuTe5qYWv5wJ/nnkBvyH07bGn9NLO2xzbU4ZLCbgPLQS9MTozKnuz9BHJ1Fk8ohvdviolJWnFWBaHzR+ApOwJPWWyC89xvs= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788914192; c=relaxed/simple; bh=uEkNOSXdC46fBSKvC67KtHisaHlBg6/KZGHd24F4+1I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eXMbvwEztyTD6K5xOMX1jLk9VUNAcqVpMWu+0czCJjCo37i8qpvW2o2vrtpcfMqJPXfBvLo24UM44mpJwW4CDfdmzBrTiVpXQRYtLbTsvDbidbppfeATAH0x6osLkiiwg3QhoFOkf4ToDLKP0pQrpi4zkRbISK3oIvGT8O7yCVs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Tg1qVNOH; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Tg1qVNOH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 11EA71F00AC4; Wed, 9 Sep 2026 00:36:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788914191; bh=XNyyy7wvsl6O1duKjrsHo2+CvjK7g9X+tV2cywrx+Zs=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Tg1qVNOHIBM5KOBt54eoJ82+Z6rFmx97HY6SyZGs3uU+dcCQvYNuqu+JC5bQlKmdB 58bg6zIFukM6tOCqrUi5Cdb48hTPlZZOl1PVaL0JaBEYfl07uqeUDZOeoZpPsK8TwU gDK9McDeQk/WVn+xNBgTOCWAcOjvTQrH09eUMcyltkVTueT9raC/uYC75vVEbXROAN Ut54YR5o3UD++4kFAtF4ge8ZdG2sLTI2PAjuPB2ACTjUG7YC1WzWZ34YxgYbG8otif zChhWEPDeyNQHzhkXokOqllvKXbNZV5bE6xCH/fqiQjRDU+zkgN5OIF7I1FydRZzVv 7XOJy8c1fyakA== From: Sasha Levin To: stable@vger.kernel.org Cc: Chuck Lever , Chris Mason , Sasha Levin Subject: [PATCH 6.6.y 4/4] svcrdma: Reject inline replies that overflow the pull-up buffer Date: Tue, 8 Sep 2026 20:36:27 -0400 Message-ID: <20260909003627.747182-4-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260909003627.747182-1-sashal@kernel.org> References: <2026090317-dining-snippet-cb36@gregkh> <20260909003627.747182-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Chuck Lever [ 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 Assisted-by: kres:claude-opus-4-7 Link: https://patch.msgid.link/20260623014728.826032-1-cel@kernel.org Signed-off-by: Chuck Lever Signed-off-by: Sasha Levin --- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 47 ++++++++++++++++++--------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 175d3a0478c26..078157b66418f 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -656,20 +656,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 = { @@ -681,11 +682,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; } /** @@ -741,7 +753,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 @@ -775,6 +787,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 * @@ -790,6 +803,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; @@ -804,7 +818,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, @@ -983,7 +1000,7 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) if (!pcl_is_empty(&rctxt->rc_reply_pcl)) { ret = svc_rdma_send_reply_chunk(rdma, rctxt, &rqstp->rq_res); if (ret < 0) - goto reply_chunk; + goto send_err; rc_size = ret; } @@ -1004,10 +1021,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; -- 2.53.0