Skip to content

Commit 848a4eb

Browse files
chuckleverTrond Myklebust
authored andcommitted
NFSv4.0: Remove cl_ipaddr from non-UCS client ID
It is possible for two distinct clients to have the same cl_ipaddr: - if the client admin disables callback with clientaddr=0.0.0.0 on more than one client - if two clients behind separate NATs use the same private subnet number - if the client admin specifies the same address via clientaddr= mount option (pointing the server at the same NAT box, for example) Because of the way the Linux NFSv4.0 client constructs its client ID string by default, such clients could interfere with each others' lease state when mounting the same server: scnprintf(str, len, "Linux NFSv4.0 %s/%s %s", clp->cl_ipaddr, rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR), rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)); cl_ipaddr is set to the value of the clientaddr= mount option. Two clients whose addresses are 192.168.3.77 that mount the same server (whose public IP address is, say, 3.4.5.6) would both generate the same client ID string when sending a SETCLIENTID: Linux NFSv4.0 192.168.3.77/3.4.5.6 tcp and thus the server would not be able to distinguish the clients' leases. If both clients are using AUTH_SYS when sending SETCLIENTID then the server could possibly permit the two clients to interfere with or purge each others' leases. To better ensure that Linux's NFSv4.0 client ID strings are distinct in these cases, remove cl_ipaddr from the client ID string and replace it with something more likely to be unique. Note that the replacement looks a lot like the uniform client ID string. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
1 parent 977294c commit 848a4eb

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

fs/nfs/nfs4proc.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5618,13 +5618,16 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
56185618
return 0;
56195619

56205620
rcu_read_lock();
5621-
len = 14 + strlen(clp->cl_ipaddr) + 1 +
5621+
len = 14 +
5622+
strlen(clp->cl_rpcclient->cl_nodename) +
5623+
1 +
56225624
strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
56235625
1 +
56245626
strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)) +
56255627
1;
56265628
rcu_read_unlock();
5627-
5629+
if (nfs4_client_id_uniquifier[0] != '\0')
5630+
len += strlen(nfs4_client_id_uniquifier) + 1;
56285631
if (len > NFS4_OPAQUE_LIMIT + 1)
56295632
return -EINVAL;
56305633

@@ -5638,10 +5641,21 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
56385641
return -ENOMEM;
56395642

56405643
rcu_read_lock();
5641-
scnprintf(str, len, "Linux NFSv4.0 %s/%s %s",
5642-
clp->cl_ipaddr,
5643-
rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR),
5644-
rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO));
5644+
if (nfs4_client_id_uniquifier[0] != '\0')
5645+
scnprintf(str, len, "Linux NFSv4.0 %s/%s/%s %s",
5646+
clp->cl_rpcclient->cl_nodename,
5647+
nfs4_client_id_uniquifier,
5648+
rpc_peeraddr2str(clp->cl_rpcclient,
5649+
RPC_DISPLAY_ADDR),
5650+
rpc_peeraddr2str(clp->cl_rpcclient,
5651+
RPC_DISPLAY_PROTO));
5652+
else
5653+
scnprintf(str, len, "Linux NFSv4.0 %s/%s %s",
5654+
clp->cl_rpcclient->cl_nodename,
5655+
rpc_peeraddr2str(clp->cl_rpcclient,
5656+
RPC_DISPLAY_ADDR),
5657+
rpc_peeraddr2str(clp->cl_rpcclient,
5658+
RPC_DISPLAY_PROTO));
56455659
rcu_read_unlock();
56465660

56475661
clp->cl_owner_id = str;

0 commit comments

Comments
 (0)