From: Bjoern Doebel <doebel@amazon.de>
To: <stable@vger.kernel.org>
Cc: Chuck Lever <cel@kernel.org>,
Kimi Security Team <bug-report@moonshot.ai>,
Yilin Zhang <yilinzhang@moonshot.ai>,
Bjoern Doebel <doebel@amazon.de>
Subject: [PATCH 5.10.y v2] SUNRPC: Copy the deferred RPC Call from the head buffer
Date: Thu, 12 Nov 2026 13:55:43 +0000 [thread overview]
Message-ID: <20261112135550.982415-1-doebel@amazon.de> (raw)
In-Reply-To: <20261112134001.952224-1-doebel@amazon.de>
From: Chuck Lever <cel@kernel.org>
commit 2192a56b0686599358909c3e12e9a366f5b5d452 upstream.
svc_defer() snapshots the RPC Call for replay once a pending cache
upcall resolves. It copies the Call starting (rq_arg.len -
head[0].iov_len) bytes before head[0].iov_base, a back-up that once
covered a transport header. No transport has had one since commit
983084b2672c ("SUNRPC: Remove svc_rqst::rq_xprt_hlen"), so the two
lengths are meant to be equal.
An RPCSEC_GSS Call breaks that assumption. Unwrapping the integrity
service truncates rq_arg.len by the length of the trailing checksum,
and unwrapping the privacy service leaves rq_arg.len short by an
amount the client sets with trailing bytes after the wrap token.
Neither adjusts head[0].iov_len. Both lengths are size_t, so the
subtraction underflows and the copy starts past head[0].iov_base.
Every deferred integrity Call replays a shifted snapshot.
A deferred replay skips GSS verification, so a shifted snapshot runs
as an authenticated Call. With the privacy service the offset is
client-chosen. A forged Call placed in that window, naming another
user's GSS context handle, runs under that identity.
Copy the Call from head[0].iov_base. Refuse to defer a Call whose
length runs past the head buffer, so the copy cannot read out of
bounds.
Fixes: 260c1d1298f6 ("svc: Add transport hdr size for defer/revisit")
Cc: stable@vger.kernel.org
Reported-by: Kimi Security Team <bug-report@moonshot.ai>
Reported-by: Yilin Zhang <yilinzhang@moonshot.ai>
Link: https://patch.msgid.link/20260902133101.48914-1-cel@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
[doebel: 5.10 lacks 983084b2672c; keep xprt_hlen and its comments in
svc_deferred_recv(). The removed skip is zero for all 5.10 transports.]
Signed-off-by: Bjoern Doebel <doebel@amazon.de>
---
v2:
- Add the "commit <sha1> upstream." line.
- Document why the backport differs from upstream.
net/sunrpc/svc_xprt.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 60782504ad3e7..a8bd4f7f9299d 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -1181,13 +1181,8 @@ static void svc_revisit(struct cache_deferred_req *dreq, int too_many)
}
/*
- * Save the request off for later processing. The request buffer looks
- * like this:
- *
- * <xprt-header><rpc-header><rpc-pagelist><rpc-tail>
- *
- * This code can only handle requests that consist of an xprt-header
- * and rpc-header.
+ * Save the request off for later processing. Only a Call that fits
+ * entirely in rq_arg.head[0] can be deferred.
*/
static struct cache_deferred_req *svc_defer(struct cache_req *req)
{
@@ -1200,8 +1195,11 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
dr = rqstp->rq_deferred;
rqstp->rq_deferred = NULL;
} else {
- size_t skip;
size_t size;
+
+ if (rqstp->rq_arg.len > rqstp->rq_arg.head[0].iov_len)
+ return NULL;
+
/* FIXME maybe discard if size too large */
size = sizeof(struct svc_deferred_req) + rqstp->rq_arg.len;
dr = kmalloc(size, GFP_KERNEL);
@@ -1216,9 +1214,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
dr->argslen = rqstp->rq_arg.len >> 2;
dr->xprt_hlen = rqstp->rq_xprt_hlen;
- /* back up head to the start of the buffer and copy */
- skip = rqstp->rq_arg.len - rqstp->rq_arg.head[0].iov_len;
- memcpy(dr->args, rqstp->rq_arg.head[0].iov_base - skip,
+ memcpy(dr->args, rqstp->rq_arg.head[0].iov_base,
dr->argslen << 2);
}
trace_svc_defer(rqstp);
--
2.50.1
next prev parent reply other threads:[~2026-11-12 13:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-04 18:54 FAILED: patch "[PATCH] SUNRPC: Copy the deferred RPC Call from the head buffer" failed to apply to 5.10-stable tree gregkh
2026-11-12 13:40 ` [PATCH 5.10.y] SUNRPC: Copy the deferred RPC Call from the head buffer Bjoern Doebel
2026-11-12 13:55 ` Bjoern Doebel [this message]
2026-11-13 2:33 ` [PATCH 5.10.y v2] " Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261112135550.982415-1-doebel@amazon.de \
--to=doebel@amazon.de \
--cc=bug-report@moonshot.ai \
--cc=cel@kernel.org \
--cc=stable@vger.kernel.org \
--cc=yilinzhang@moonshot.ai \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.