summaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2018-06-04 10:53:29 -0400
committerTrond Myklebust <trond.myklebust@hammerspace.com>2018-06-06 11:45:44 -0400
commit848a4eb2e3972400b683bf525a84fdaff6f6dbcc (patch)
tree22ee36eb1be638d6437457905c28cf06813f145a /fs/nfs
parent977294c7199ed84d4878a63781a67014e1f0efe8 (diff)
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>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c26
1 files changed, 20 insertions, 6 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index e7998772bc51..fda45ff7a653 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5618,13 +5618,16 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
5618 return 0; 5618 return 0;
5619 5619
5620 rcu_read_lock(); 5620 rcu_read_lock();
5621 len = 14 + strlen(clp->cl_ipaddr) + 1 + 5621 len = 14 +
5622 strlen(clp->cl_rpcclient->cl_nodename) +
5623 1 +
5622 strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) + 5624 strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)) +
5623 1 + 5625 1 +
5624 strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)) + 5626 strlen(rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)) +
5625 1; 5627 1;
5626 rcu_read_unlock(); 5628 rcu_read_unlock();
5627 5629 if (nfs4_client_id_uniquifier[0] != '\0')
5630 len += strlen(nfs4_client_id_uniquifier) + 1;
5628 if (len > NFS4_OPAQUE_LIMIT + 1) 5631 if (len > NFS4_OPAQUE_LIMIT + 1)
5629 return -EINVAL; 5632 return -EINVAL;
5630 5633
@@ -5638,10 +5641,21 @@ nfs4_init_nonuniform_client_string(struct nfs_client *clp)
5638 return -ENOMEM; 5641 return -ENOMEM;
5639 5642
5640 rcu_read_lock(); 5643 rcu_read_lock();
5641 scnprintf(str, len, "Linux NFSv4.0 %s/%s %s", 5644 if (nfs4_client_id_uniquifier[0] != '\0')
5642 clp->cl_ipaddr, 5645 scnprintf(str, len, "Linux NFSv4.0 %s/%s/%s %s",
5643 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR), 5646 clp->cl_rpcclient->cl_nodename,
5644 rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_PROTO)); 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));
5645 rcu_read_unlock(); 5659 rcu_read_unlock();
5646 5660
5647 clp->cl_owner_id = str; 5661 clp->cl_owner_id = str;