[PATCH 3/5] NFSv4/pNFS: check the sscanf return in nfs4_decode_mp_ds_addr

Junrui Luo via B4 Relay <[email protected]> Tue, 04 Aug 2026 18:55:03 +0800
Newsgroups gmane.linux.kernel.stable,gmane.linux.nfs,gmane.linux.kernel
Message-ID <[email protected]>
From: Junrui Luo <[email protected]>

nfs4_decode_mp_ds_addr() splits the r_addr opaque of a netaddr4 into an
address part and a trailing ".ABC.DEF" port pair using two strrchr()
passes. The address part is validated by rpc_pton(), which is passed an
explicit length of portstr - buf and never inspects the port octets.

The port octets are converted with sscanf(portstr, "%d-%d", &tmp[0],
&tmp[1]) and the return value is discarded. tmp[] is uninitialised and
nothing constrains the characters after the last two dots, so an r_addr
such as "192.168.1.1.x.y" leaves both elements unwritten. The stale
stack contents then become the destination port of the data server
connection and are rendered into da_remotestr, potentially leaking
client stack memory to the metadata server.

Fix by requiring both conversions to succeed and rejecting the address
otherwise via the existing out_free_da path, matching the port octet
validation in rpc_uaddr2sockaddr().

Fixes: 16b374ca439f ("NFSv4.1: pnfs: filelayout: add driver's LAYOUTGET and GETDEVICEINFO infrastructure")
Reported-by: Yuhao Jiang <[email protected]>
Assisted-by: Claude:claude-opus-5
Cc: [email protected]
Signed-off-by: Junrui Luo <[email protected]>
---
 fs/nfs/pnfs_nfs.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index 648c95b78eea..63fb3695fdb9 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -1114,7 +1114,8 @@ nfs4_decode_mp_ds_addr(struct net *net, struct xdr_stream *xdr, gfp_t gfp_flags)
 	}
 
 	portstr++;
-	sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]);
+	if (sscanf(portstr, "%d-%d", &tmp[0], &tmp[1]) != 2)
+		goto out_free_da;
 	port = htons((tmp[0] << 8) | (tmp[1]));
 
 	switch (da->da_addr.ss_family) {

-- 
2.51.2