[PATCH v2] NFS: reject oversized callback bitmap lengths

Jiancheng Huang posted 1 patch 5 hours ago
fs/nfs/callback_xdr.c | 2 ++
1 file changed, 2 insertions(+)
[PATCH v2] NFS: reject oversized callback bitmap lengths
Posted by Jiancheng Huang 5 hours ago
decode_bitmap() stores at most three bitmap words, but shifts the
server-supplied word count before validating it. A large attrlen can wrap
the byte count passed to xdr_inline_decode() and leave the fixed-word
reads outside the XDR carrier.

Reject lengths larger than the local three-word representation before the
shift and return NFS4ERR_INVAL for malformed callbacks.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Jiancheng Huang <jchuang@seu.edu.cn>
Assisted-by: Codex:gpt-5.6-luna
---
Changes in v2:
- Add the relevant public mailing lists to Cc; no source changes.

Evidence (v7.2-rc4 KUnit/KASAN oracle under bounded QEMU):
Source: confirmed/nfs_callback_bitmap_overflow_raw_excerpt.log

[    2.650597] KTAP version 1
[    2.650657] 1..1
[    2.653395]     KTAP version 1
[    2.653578]     # Subtest: nfs-callback-bitmap-overflow
[    2.653841]     # module: nfsv4
[    2.653979]     1..2
[    2.658646]     ok 1 nfs_callback_bitmap_overflow_test
[    2.660479] ==================================================================
[    2.660763] BUG: KASAN: stack-out-of-bounds in decode_bitmap+0x1e6/0x240
[    2.661084] Read of size 4 at addr ffff888002f47ab0 by task kunit_try_catch/69
[    2.661084] 
[    2.661084] CPU: 1 UID: 0 PID: 69 Comm: kunit_try_catch Tainted: G                 N  7.2.0-rc4-dirty #3 PREEMPT(full) 
[    2.661084] Tainted: [N]=TEST
[    2.661084] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[    2.661084] Call Trace:
[    2.661084]  <TASK>
[    2.661084]  dump_stack_lvl+0x53/0x70
[    2.661084]  print_report+0xd0/0x630
[    2.661084]  ? __pfx__raw_spin_lock_irqsave+0x10/0x10
[    2.661084]  ? decode_bitmap+0x1e6/0x240
[    2.661084]  kasan_report+0xe5/0x120
[    2.661084]  ? decode_bitmap+0x1e6/0x240

 fs/nfs/callback_xdr.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index 4382baddc..9dcee0dca 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -109,6 +109,8 @@ static __be32 decode_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
 	if (unlikely(p == NULL))
 		return htonl(NFS4ERR_RESOURCE);
 	attrlen = ntohl(*p);
+	if (attrlen > 3)
+		return htonl(NFS4ERR_INVAL);
 	p = xdr_inline_decode(xdr, attrlen << 2);
 	if (unlikely(p == NULL))
 		return htonl(NFS4ERR_RESOURCE);
-- 
2.43.0