fs/nfs/callback_xdr.c | 2 ++ 1 file changed, 2 insertions(+)
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
© 2016 - 2026 Red Hat, Inc.