Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Sean Chang and committed by
Trond Myklebust
e6614b88 e8a44ae8

+13 -3
+13 -3
fs/nfs/super.c
··· 1166 1166 static int nfs_compare_super_address(struct nfs_server *server1, 1167 1167 struct nfs_server *server2) 1168 1168 { 1169 + struct rpc_xprt *xprt1, *xprt2; 1169 1170 struct sockaddr *sap1, *sap2; 1170 - struct rpc_xprt *xprt1 = server1->client->cl_xprt; 1171 - struct rpc_xprt *xprt2 = server2->client->cl_xprt; 1171 + 1172 + rcu_read_lock(); 1173 + 1174 + xprt1 = rcu_dereference(server1->client->cl_xprt); 1175 + xprt2 = rcu_dereference(server2->client->cl_xprt); 1172 1176 1173 1177 if (!net_eq(xprt1->xprt_net, xprt2->xprt_net)) 1174 - return 0; 1178 + goto out_unlock; 1179 + 1180 + rcu_read_unlock(); 1175 1181 1176 1182 sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr; 1177 1183 sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr; ··· 1209 1203 } 1210 1204 1211 1205 return 1; 1206 + 1207 + out_unlock: 1208 + rcu_read_unlock(); 1209 + return 0; 1212 1210 } 1213 1211 1214 1212 static int nfs_compare_userns(const struct nfs_server *old,