mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] nfsd: prevent NFSv4.1 SEQUENCE reply-cache overflow
@ 2026-09-22 11:26 Mayank Jangid (OpenSec Intelligence)
  2026-09-22 14:06 ` Chuck Lever
  0 siblings, 1 reply; 3+ messages in thread
From: Mayank Jangid (OpenSec Intelligence) @ 2026-09-22 11:26 UTC (permalink / raw)
  To: cel, jlayton
  Cc: neil, okorniev, Dai.Ngo, tom, linux-nfs, linux-kernel, security,
	Mayank Jangid (OpenSec Intelligence),
	Kushal Khemka, Kkartik Aggarwal

nfsd4_sequence() narrows the reply buffer to the session cached-response
limit before accepting the slot sequence ID. A client can negotiate
ca_maxresponsesize_cached down to NFSD_MIN_HDR_SEQ_SZ, leaving no storage
in the slot trailing sl_data[] array.

A padded COMPOUND tag can then leave enough space for the SEQUENCE opcode
but not its status word. The encoder returns without setting
cstate.data_offset, and nfsd4_sequence_done() consequently copies the
whole reply from offset zero into the zero-capacity slot cache, causing a
heap out-of-bounds write.

Compute the fixed SEQUENCE reply size, including room for a following
operation error when necessary, before restricting the reply buffer and
accepting the slot. Return NFS4ERR_REP_TOO_BIG_TO_CACHE without changing
the slot when the result cannot fit.

Also record the appropriate NFS error when an operation header cannot be
encoded. This prevents an incomplete operation from remaining marked
successful and being treated as cacheable.

Fixes: 47ee52986472 ("nfsd4: adjust buflen to session channel limit")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Co-developed-by: Kushal Khemka (OpenSec Intelligence) <kushalkhemka559@gmail.com>
Signed-off-by: Kushal Khemka (OpenSec Intelligence) <kushalkhemka559@gmail.com>
Co-developed-by: Kkartik Aggarwal (OpenSec Intelligence) <aggarwalkkartik@gmail.com>
Signed-off-by: Kkartik Aggarwal (OpenSec Intelligence) <aggarwalkkartik@gmail.com>
Signed-off-by: Mayank Jangid (OpenSec Intelligence) <mayank.jangid.moon@gmail.com>
---
 fs/nfsd/nfs4state.c | 18 +++++++++++++++++-
 fs/nfsd/nfs4xdr.c   | 12 ++++++++++--
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9c4adf311..6c246d851 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -5016,6 +5016,7 @@ __be32
 nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		union nfsd4_op_u *u)
 {
+	struct nfsd4_compoundargs *args = rqstp->rq_argp;
 	struct nfsd4_sequence *seq = &u->sequence;
 	struct nfsd4_compoundres *resp = rqstp->rq_resp;
 	struct xdr_stream *xdr = resp->xdr;
@@ -5025,6 +5026,7 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct nfsd4_conn *conn;
 	__be32 status;
 	int buflen;
+	u32 maxlen, respsize;
 	struct net *net = SVC_NET(rqstp);
 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 
@@ -5102,7 +5104,21 @@ nfsd4_sequence(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 			session->se_fchannel.maxresp_sz;
 	status = (seq->cachethis) ? nfserr_rep_too_big_to_cache :
 				    nfserr_rep_too_big;
-	if (xdr_restrict_buflen(xdr, buflen - rqstp->rq_auth_slack))
+	if (buflen < rqstp->rq_auth_slack)
+		goto out_put_session;
+	maxlen = buflen - rqstp->rq_auth_slack;
+
+	/*
+	 * Ensure the SEQUENCE result and, when needed, the next operation's
+	 * error result fit before narrowing the buffer and accepting the slot.
+	 */
+	respsize = nfsd4_max_reply(rqstp, &args->ops[0]);
+	if (!nfsd4_last_compound_op(rqstp))
+		respsize += COMPOUND_ERR_SLACK_SPACE;
+	if (xdr->buf->len > maxlen || respsize > maxlen - xdr->buf->len)
+		goto out_put_session;
+
+	if (xdr_restrict_buflen(xdr, maxlen))
 		goto out_put_session;
 	svc_reserve_auth(rqstp, buflen);
 
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 606ddcb08..e5489eec6 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -6637,11 +6637,19 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
 	unsigned int op_status_offset;
 	nfsd4_enc encoder;
 
-	if (xdr_stream_encode_u32(xdr, op->opnum) != XDR_UNIT)
+	/*
+	 * nfsd4_proc_compound() stops only when op->status records an error.
+	 * Do not leave an operation that has no encoded header marked nfs_ok.
+	 */
+	if (xdr_stream_encode_u32(xdr, op->opnum) != XDR_UNIT) {
+		op->status = nfsd4_check_resp_size(resp, XDR_UNIT * 2);
 		goto release;
+	}
 	op_status_offset = xdr->buf->len;
-	if (!xdr_reserve_space(xdr, XDR_UNIT))
+	if (!xdr_reserve_space(xdr, XDR_UNIT)) {
+		op->status = nfsd4_check_resp_size(resp, XDR_UNIT);
 		goto release;
+	}
 
 	if (op->opnum == OP_ILLEGAL)
 		goto status;

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] nfsd: prevent NFSv4.1 SEQUENCE reply-cache overflow
  2026-09-22 11:26 [PATCH] nfsd: prevent NFSv4.1 SEQUENCE reply-cache overflow Mayank Jangid (OpenSec Intelligence)
@ 2026-09-22 14:06 ` Chuck Lever
  2026-09-23  0:37   ` Mayank Jangid
  0 siblings, 1 reply; 3+ messages in thread
From: Chuck Lever @ 2026-09-22 14:06 UTC (permalink / raw)
  To: Mayank Jangid (OpenSec Intelligence)
  Cc: jlayton, neil, okorniev, Dai.Ngo, tom, linux-nfs, linux-kernel,
	security, Kushal Khemka, Kkartik Aggarwal

On 9/22/26 7:26 AM, Mayank Jangid (OpenSec Intelligence) wrote:
> nfsd4_sequence() narrows the reply buffer to the session cached-response
> limit before accepting the slot sequence ID. A client can negotiate
> ca_maxresponsesize_cached down to NFSD_MIN_HDR_SEQ_SZ, leaving no storage
> in the slot trailing sl_data[] array.

Thanks for the report and the patch. Jérémy Jean reported the same
issue in August, and a fix for it is already queued in the nfsd-testing
branch:

  https://lore.kernel.org/linux-nfs/20260817-jean-v1-0-9e356596ab85@kernel.org/

Patch 1/2 there adds the same pre-flight check of the SEQUENCE reply
size before nfsd4_sequence() narrows the buffer and accepts the slot,
and patch 2/2 sets op->status when an operation header cannot be
encoded. Your patch does the same two things, so I won't apply it on
top of that series.

If you can test the queued fix against your reproducer and confirm it
addresses the overflow you found, a Tested-by: on that thread would be
welcome.

-- 
Chuck Lever (Come to NFS bake-a-thon! https://nfsv4bat.org)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] nfsd: prevent NFSv4.1 SEQUENCE reply-cache overflow
  2026-09-22 14:06 ` Chuck Lever
@ 2026-09-23  0:37   ` Mayank Jangid
  0 siblings, 0 replies; 3+ messages in thread
From: Mayank Jangid @ 2026-09-23  0:37 UTC (permalink / raw)
  To: Chuck Lever
  Cc: jlayton, neil, okorniev, Dai.Ngo, tom, linux-nfs, linux-kernel,
	security, Kushal Khemka, Kkartik Aggarwal

Hi Chuck,

Thanks for pointing me to Jérémy's series.

I tested the queued fix against our reproducer, and it resolves the issue. I can no longer reproduce the reply buffer overflow with the two patches applied.

Please feel free to add:
Tested-by: Mayank Jangid (OpenSec Intelligence) mayank.jangid.moon@gmail.com <mailto:mayank.jangid.moon@gmail.com>

Thanks,
Mayank Jangid
OpenSec Intelligence

> On 22 Sep 2026, at 7:36 PM, Chuck Lever <cel@kernel.org> wrote:
> 
> On 9/22/26 7:26 AM, Mayank Jangid (OpenSec Intelligence) wrote:
>> nfsd4_sequence() narrows the reply buffer to the session cached-response
>> limit before accepting the slot sequence ID. A client can negotiate
>> ca_maxresponsesize_cached down to NFSD_MIN_HDR_SEQ_SZ, leaving no storage
>> in the slot trailing sl_data[] array.
> 
> Thanks for the report and the patch. Jérémy Jean reported the same
> issue in August, and a fix for it is already queued in the nfsd-testing
> branch:
> 
>  https://lore.kernel.org/linux-nfs/20260817-jean-v1-0-9e356596ab85@kernel.org/
> 
> Patch 1/2 there adds the same pre-flight check of the SEQUENCE reply
> size before nfsd4_sequence() narrows the buffer and accepts the slot,
> and patch 2/2 sets op->status when an operation header cannot be
> encoded. Your patch does the same two things, so I won't apply it on
> top of that series.
> 
> If you can test the queued fix against your reproducer and confirm it
> addresses the overflow you found, a Tested-by: on that thread would be
> welcome.
> 
> -- 
> Chuck Lever (Come to NFS bake-a-thon! https://nfsv4bat.org)


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-09-23  0:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-22 11:26 [PATCH] nfsd: prevent NFSv4.1 SEQUENCE reply-cache overflow Mayank Jangid (OpenSec Intelligence)
2026-09-22 14:06 ` Chuck Lever
2026-09-23  0:37   ` Mayank Jangid

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®