[PATCH] NFSv4.1: fix out-of-bounds write from zero back channel ca_maxrequests

From: Paula

Date: Wed Aug 19 2026 - 13:01:53 EST


nfs4_verify_back_channel_attrs() validates the channel attributes a
server returns in a CREATE_SESSION reply before they are used to size
the back channel slot table. Unlike its fore channel sibling
nfs4_verify_fore_channel_attrs(), it never rejects a back channel
ca_maxrequests (rcvd->max_reqs) of zero.

A zero value reaches nfs4_realloc_slot_table(), where
nfs4_reset_slot_table() derives both server_highest_slotid and
max_slotid from max_reqs - 1. The subtraction is unsigned, so zero
underflows to 0xffffffff and is stored as the table's slot-id ceiling.

The attributes are chosen by the server in its CREATE_SESSION response:
a malicious or compromised NFSv4.1 server, on the wire, with no
authentication under sec=sys, and before the mount completes.

With server_highest_slotid and max_slotid at 0xffffffff, the bounds
checks in nfs4_lookup_slot() (slotid <= max_slotid) and validate_seqid()
(csa_slotid > server_highest_slotid) no longer constrain the
server-chosen CB_SEQUENCE csa_slotid. nfs4_lock_slot() then runs
__set_bit(slotid, tbl->used_slots) against the fixed used_slots[] array,
which is only SLOT_TABLE_SZ (16) unsigned longs / 1024 bits. A csa_slotid
of 3584 sets a bit 448 bytes past the array, a slab-out-of-bounds write
into the neighbouring allocation. The slot id is server-controlled, so
the write offset is attacker-chosen and deterministic.

KASAN labels the access below "Read of size 8" because __set_bit() is a
read-modify-write and the sanitizer flags the load; the store is the
actual defect, hence "out-of-bounds write".

BUG: KASAN: slab-out-of-bounds in nfs4_lock_slot+0x148/0x15c
Read of size 8 at addr ffff0000c7232bf0 by task NFSv4 callback/235
Call trace:
nfs4_lock_slot+0x148/0x15c
nfs4_try_to_lock_slot+0x74/0xc0
nfs4_callback_sequence+0x850/0x141c
nfs4_callback_compound+0x414/0x111c
nfs_callback_dispatch+0x6c/0xf4
svc_process_common+0xb3c/0x1ba4
svc_process_bc+0x400/0x9bc
svc_recv+0xb5c/0x23fc
nfs4_callback_svc+0xa8/0x140
kthread+0x32c/0x3e4
ret_from_fork+0x10/0x20

Allocated by task 234:
__kmalloc_cache_noprof+0x188/0x480
nfs4_alloc_session+0x44/0x260
nfs41_init_client+0x18/0x80
nfs4_init_client+0x120/0x440
nfs4_set_client+0x310/0x5a0
nfs4_create_server+0x124/0x234
nfs4_try_get_tree+0x70/0x240
vfs_get_tree+0x74/0x2c0

Reachable with CONFIG_NFS_V4_1 whenever the client mounts an NFSv4.1
export from a server the attacker controls or can spoof.

Reject a zero back channel ca_maxrequests in
nfs4_verify_back_channel_attrs(), as nfs4_verify_fore_channel_attrs()
already does, so the underflow never sizes the slot table. The error
propagates through nfs4_verify_channel_attrs() and aborts
nfs4_proc_create_session() before nfs4_update_session() installs the
poisoned ceiling.

Fixes: 5405fc44c337 ("NFSv4.x: Add kernel parameter to control the callback server")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Bynario AI
Signed-off-by: Paula <paula@xxxxxxxx>
---
fs/nfs/nfs4proc.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5709c6fea..182078c2e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -9161,6 +9161,8 @@ static int nfs4_verify_back_channel_attrs(struct nfs41_create_session_args *args
return -EINVAL;
if (rcvd->max_resp_sz_cached > sent->max_resp_sz_cached)
return -EINVAL;
+ if (rcvd->max_reqs == 0)
+ return -EINVAL;
if (rcvd->max_ops > sent->max_ops)
return -EINVAL;
if (rcvd->max_reqs > sent->max_reqs)

base-commit: 3a0dd7ba4f44cdc116d83712f61e7c1a95be3588
--
2.50.1 (Apple Git-155)