[PATCH] NFSv4: fix bitmap length check in decode_bitmap()
From: Guanglei Zhu
Date: Mon Oct 12 2026 - 05:11:25 EST
decode_bitmap() reads attrlen from the callback message and passes
attrlen << 2 to xdr_inline_decode() as the number of bytes to
consume. The shift is done in 32-bit arithmetic, so an attrlen of
0x40000000 wraps to zero, the bounds check in
__xdr_inline_decode() passes, and the subsequent reads of
bitmap[0..2] walk up to 12 bytes past the end of the received
buffer.
Reject attrlen values larger than 3, the size of the bitmap array.
Signed-off-by: Guanglei Zhu <zhugl3@xxxxxxxxxxxx>
---
Verified with an ASAN build of an exact user-space replica of
decode_bitmap() and __xdr_inline_decode(): attrlen=0x40000000 with
the message ending right after the attrlen word results in a
heap-buffer-overflow READ of size 4, 0 bytes after the allocation.
fs/nfs/callback_xdr.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 88e1af0fd..bea967e0c 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -109,6 +109,9 @@ static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
if (unlikely(p == NULL))
return htonl(NFS4ERR_RESOURCE);
attrlen = ntohl(*p);
+ /* bitmap[] has only 3 words; also stops attrlen<<2 from wrapping */
+ if (unlikely(attrlen > 3))
+ return htonl(NFS4ERR_BADXDR);
p = xdr_inline_decode(xdr, attrlen << 2);
if (unlikely(p == NULL))
return htonl(NFS4ERR_RESOURCE);
--
2.43.0