mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Mayank Jangid (OpenSec Intelligence)" <mayank.jangid.moon@gmail.com>
To: cel@kernel.org, jlayton@kernel.org
Cc: neil@brown.name, okorniev@redhat.com, Dai.Ngo@oracle.com,
	tom@talpey.com, linux-nfs@vger.kernel.org,
	linux-kernel@vger.kernel.org, security@kernel.org,
	"Mayank Jangid (OpenSec Intelligence)"
	<mayank.jangid.moon@gmail.com>,
	Kushal Khemka <kushalkhemka559@gmail.com>,
	Kkartik Aggarwal <aggarwalkkartik@gmail.com>
Subject: [PATCH] nfsd: prevent NFSv4.1 SEQUENCE reply-cache overflow
Date: Tue, 22 Sep 2026 11:26:08 +0000	[thread overview]
Message-ID: <20260922112608.1256363-1-mayank.jangid.moon@gmail.com> (raw)

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;

             reply	other threads:[~2026-09-22 11:26 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-22 11:26 Mayank Jangid (OpenSec Intelligence) [this message]
2026-09-22 14:06 ` Chuck Lever
2026-09-23  0:37   ` Mayank Jangid

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=20260922112608.1256363-1-mayank.jangid.moon@gmail.com \
    --to=mayank.jangid.moon@gmail.com \
    --cc=Dai.Ngo@oracle.com \
    --cc=aggarwalkkartik@gmail.com \
    --cc=cel@kernel.org \
    --cc=jlayton@kernel.org \
    --cc=kushalkhemka559@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --cc=security@kernel.org \
    --cc=tom@talpey.com \
    /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 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®