nfsd: fix clid_inuse on mount with security change
In bakeathon testing Solaris client was getting CLID_INUSE error when doing a krb5 mount soon after an auth_sys mount, or vice versa. That's not really necessary since in this case the old client doesn't have any state any more: http://tools.ietf.org/html/rfc7530#page-103 "when the server gets a SETCLIENTID for a client ID that currently has no state, or it has state but the lease has expired, rather than returning NFS4ERR_CLID_INUSE, the server MUST allow the SETCLIENTID and confirm the new client ID if followed by the appropriate SETCLIENTID_CONFIRM." This doesn't fix the problem completely since our client_has_state() check counts openowners left around to handle close replays, which we should probably just remove in this case. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
This commit is contained in:
parent
778620364e
commit
2b63482185
1 changed files with 8 additions and 2 deletions
|
@ -2262,7 +2262,8 @@ static bool client_has_state(struct nfs4_client *clp)
|
|||
* Note clp->cl_openowners check isn't quite right: there's no
|
||||
* need to count owners without stateid's.
|
||||
*
|
||||
* Also note we should probably be using this in 4.0 case too.
|
||||
* Also note in 4.0 case should also be checking for openowners
|
||||
* kept around just for close handling.
|
||||
*/
|
||||
return !list_empty(&clp->cl_openowners)
|
||||
#ifdef CONFIG_NFSD_PNFS
|
||||
|
@ -3049,7 +3050,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|||
/* Cases below refer to rfc 3530 section 14.2.33: */
|
||||
spin_lock(&nn->client_lock);
|
||||
conf = find_confirmed_client_by_name(&clname, nn);
|
||||
if (conf) {
|
||||
if (conf && client_has_state(conf)) {
|
||||
/* case 0: */
|
||||
status = nfserr_clid_inuse;
|
||||
if (clp_used_exchangeid(conf))
|
||||
|
@ -3136,6 +3137,11 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
|
|||
} else { /* case 3: normal case; new or rebooted client */
|
||||
old = find_confirmed_client_by_name(&unconf->cl_name, nn);
|
||||
if (old) {
|
||||
status = nfserr_clid_inuse;
|
||||
if (client_has_state(old)
|
||||
&& !same_creds(&unconf->cl_cred,
|
||||
&old->cl_cred))
|
||||
goto out;
|
||||
status = mark_client_expired_locked(old);
|
||||
if (status) {
|
||||
old = NULL;
|
||||
|
|
Loading…
Reference in a new issue