nfsd: fix clid_inuse on mount with security change
Subsystems (2)
PATCH 1/2 nfsd: fix clid_inuse on mount with security change
From: "J. Bruce Fields" <[email protected]>
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.
--- fs/nfsd/nfs4state.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
fs/nfsd/nfs4state.c +8 -2
@@ -2275,7 +2275,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
@@ -3062,7 +3063,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))
@@ -3149,6 +3150,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 ;
Signature · 1 line
2.4.3
PATCH 2/2 nfsd: improve client_has_state to check for unused openowners
From: "J. Bruce Fields" <[email protected]>
At least in the v4.0 case openowners can hang around for a while after last close, but they shouldn't really block (for example), a new mount with a different principal.
--- fs/nfsd/nfs4state.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
fs/nfsd/nfs4state.c +12 -8
@@ -2269,16 +2269,20 @@ nfsd4_set_ex_flags(struct nfs4_client *new, struct nfsd4_exchange_id *clid) clid->flags = new->cl_exchange_flags; } +static bool client_has_openowners (struct nfs4_client *clp) +{ +struct nfs4_openowner *oo; + +list_for_each_entry (oo, &clp->cl_openowners, oo_perclient) { +if (!list_empty (&oo->oo_owner.so_stateids)) +return true; + } +return false; +} +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 in 4.0 case should also be checking for openowners -* kept around just for close handling. -*/ - return !list_empty(&clp->cl_openowners) + return !client_has_openowners(clp)#ifdef CONFIG_NFSD_PNFS || !list_empty(&clp->cl_lo_states)#endif
Signature · 1 line
2.4.3