summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Chang <seanwascoding@gmail.com>2026-04-19 19:31:38 +0300
committerTrond Myklebust <trond.myklebust@hammerspace.com>2026-04-22 15:53:23 +0300
commite6614b88d59d110ee1a80ed0826e34f24dd35c96 (patch)
tree4cc0148ca7b6debbccf19272920170dc09258768
parente8a44ae87b553b0851a20bebf3d2634a45c5e316 (diff)
downloadlinux-e6614b88d59d110ee1a80ed0826e34f24dd35c96.tar.xz
NFS: Fix RCU dereference of cl_xprt in nfs_compare_super_address
The cl_xprt pointer in struct rpc_clnt is marked as __rcu. Accessing it directly in nfs_compare_super_address() is unsafe and triggers Sparse warnings. Fix this by using rcu_dereference() within an RCU read-side critical section to retrieve the transport pointer. This addresses the sparse warning and ensures atomic access to the pointer, as the transport can be updated via transport switching even while the superblock remains active under sb_lock. Fixes: 7e3fcf61abde ("nfs: don't share mounts between network namespaces") Signed-off-by: Sean Chang <seanwascoding@gmail.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r--fs/nfs/super.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 7a318581f85b..4cd420b14ce3 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1166,12 +1166,18 @@ static int nfs_set_super(struct super_block *s, struct fs_context *fc)
static int nfs_compare_super_address(struct nfs_server *server1,
struct nfs_server *server2)
{
+ struct rpc_xprt *xprt1, *xprt2;
struct sockaddr *sap1, *sap2;
- struct rpc_xprt *xprt1 = server1->client->cl_xprt;
- struct rpc_xprt *xprt2 = server2->client->cl_xprt;
+
+ rcu_read_lock();
+
+ xprt1 = rcu_dereference(server1->client->cl_xprt);
+ xprt2 = rcu_dereference(server2->client->cl_xprt);
if (!net_eq(xprt1->xprt_net, xprt2->xprt_net))
- return 0;
+ goto out_unlock;
+
+ rcu_read_unlock();
sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr;
sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr;
@@ -1203,6 +1209,10 @@ static int nfs_compare_super_address(struct nfs_server *server1,
}
return 1;
+
+out_unlock:
+ rcu_read_unlock();
+ return 0;
}
static int nfs_compare_userns(const struct nfs_server *old,