* [PATCH] nfsd: fix heap overflow in NFSv4.0 LOCK replay cache
@ 2026-02-24 16:33 Jeff Layton
2026-02-24 17:41 ` Chuck Lever
0 siblings, 1 reply; 2+ messages in thread
From: Jeff Layton @ 2026-02-24 16:33 UTC (permalink / raw)
To: Chuck Lever, NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey
Cc: linux-nfs, linux-kernel, security, Nicholas Carlini, Jeff Layton
The NFSv4.0 replay cache uses a fixed 112-byte inline buffer
(rp_ibuf[NFSD4_REPLAY_ISIZE]) to store encoded operation responses.
This size was calculated based on OPEN responses and does not account
for LOCK denied responses, which include the conflicting lock owner as
a variable-length field up to 1024 bytes (NFS4_OPAQUE_LIMIT).
When a LOCK operation is denied due to a conflict with an existing lock
that has a large owner, nfsd4_encode_operation() copies the full encoded
response into the undersized replay buffer via read_bytes_from_xdr_buf()
with no bounds check. This results in a slab-out-of-bounds write of up
to 944 bytes past the end of the buffer, corrupting adjacent heap memory.
This can be triggered remotely by an unauthenticated attacker with two
cooperating NFSv4.0 clients: one sets a lock with a large owner string,
then the other requests a conflicting lock to provoke the denial.
We could fix this by increasing NFSD4_REPLAY_ISIZE to allow for a full
opaque, but that would increase the size of every stateowner, when most
lockowners are not that large.
Instead, fix this by checking the encoded response length against
NFSD4_REPLAY_ISIZE before copying into the replay buffer. If the
response is too large, set rp_buflen to 0 to skip caching the replay
payload. The status is still cached, and the client already received the
correct response on the original request.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Nicholas Carlini <npc@anthropic.com>
Tested-by: Nicholas Carlini <npc@anthropic.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
AFAICT, this bug predates the move to git. I suspect it was introduced
when support for LOCK and LOCKT were added, but I didn't bother to go
poking around in the historical tree. This should probably go to all
stable kernels.
---
fs/nfsd/nfs4xdr.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 41dfba5ab8b81aca8b9449a5660b30feb9506060..9d234913100b9b3c5b3f19b307c3d80bcc517b2a 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -6281,9 +6281,14 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
int len = xdr->buf->len - (op_status_offset + XDR_UNIT);
so->so_replay.rp_status = op->status;
- so->so_replay.rp_buflen = len;
- read_bytes_from_xdr_buf(xdr->buf, op_status_offset + XDR_UNIT,
+ if (len <= NFSD4_REPLAY_ISIZE) {
+ so->so_replay.rp_buflen = len;
+ read_bytes_from_xdr_buf(xdr->buf,
+ op_status_offset + XDR_UNIT,
so->so_replay.rp_buf, len);
+ } else {
+ so->so_replay.rp_buflen = 0;
+ }
}
status:
op->status = nfsd4_map_status(op->status,
---
base-commit: 7dff99b354601dd01829e1511711846e04340a69
change-id: 20260224-v4-0-lock-overflow-67c17d99afbd
Best regards,
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [PATCH] nfsd: fix heap overflow in NFSv4.0 LOCK replay cache
2026-02-24 16:33 [PATCH] nfsd: fix heap overflow in NFSv4.0 LOCK replay cache Jeff Layton
@ 2026-02-24 17:41 ` Chuck Lever
0 siblings, 0 replies; 2+ messages in thread
From: Chuck Lever @ 2026-02-24 17:41 UTC (permalink / raw)
To: NeilBrown, Olga Kornievskaia, Dai Ngo, Tom Talpey, Jeff Layton
Cc: Chuck Lever, linux-nfs, linux-kernel, security, Nicholas Carlini
From: Chuck Lever <chuck.lever@oracle.com>
On Tue, 24 Feb 2026 11:33:35 -0500, Jeff Layton wrote:
> The NFSv4.0 replay cache uses a fixed 112-byte inline buffer
> (rp_ibuf[NFSD4_REPLAY_ISIZE]) to store encoded operation responses.
> This size was calculated based on OPEN responses and does not account
> for LOCK denied responses, which include the conflicting lock owner as
> a variable-length field up to 1024 bytes (NFS4_OPAQUE_LIMIT).
>
> When a LOCK operation is denied due to a conflict with an existing lock
> that has a large owner, nfsd4_encode_operation() copies the full encoded
> response into the undersized replay buffer via read_bytes_from_xdr_buf()
> with no bounds check. This results in a slab-out-of-bounds write of up
> to 944 bytes past the end of the buffer, corrupting adjacent heap memory.
>
> [...]
Applied to nfsd-testing, thanks!
[1/1] nfsd: fix heap overflow in NFSv4.0 LOCK replay cache
commit: 1e8e9913672a31c6fdd0d237cd3cec88435bd66e
--
Chuck Lever
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-02-24 17:41 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-24 16:33 [PATCH] nfsd: fix heap overflow in NFSv4.0 LOCK replay cache Jeff Layton
2026-02-24 17:41 ` Chuck Lever
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®