提交 fc5a96c3 编写于 作者: J Jeff Layton 提交者: J. Bruce Fields

nfsd: close potential race in nfsd4_free_stateid

Once we remove the client_mutex, it'll be possible for the sc_type of a
lock stateid to change after it's found and checked, but before we can
go to destroy it. If that happens, we can end up putting the persistent
reference to the stateid more than once, and unhash it more than once.

Fix this by unhashing the lock stateid prior to dropping the cl_lock but
after finding it.
Signed-off-by: NJeff Layton <jlayton@primarydata.com>
Signed-off-by: NJ. Bruce Fields <bfields@redhat.com>
上级 3c1c995c
......@@ -4397,17 +4397,6 @@ nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
return status;
}
static __be32
nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp)
{
struct nfs4_lockowner *lo = lockowner(stp->st_stateowner);
if (check_for_locks(stp->st_stid.sc_file, lo))
return nfserr_locks_held;
release_lock_stateid(stp);
return nfs_ok;
}
/*
* Test if the stateid is valid
*/
......@@ -4434,6 +4423,7 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
stateid_t *stateid = &free_stateid->fr_stateid;
struct nfs4_stid *s;
struct nfs4_delegation *dp;
struct nfs4_ol_stateid *stp;
struct nfs4_client *cl = cstate->session->se_client;
__be32 ret = nfserr_bad_stateid;
......@@ -4456,8 +4446,15 @@ nfsd4_free_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
ret = check_stateid_generation(stateid, &s->sc_stateid, 1);
if (ret)
break;
stp = openlockstateid(s);
ret = nfserr_locks_held;
if (check_for_locks(stp->st_stid.sc_file,
lockowner(stp->st_stateowner)))
break;
unhash_lock_stateid(stp);
spin_unlock(&cl->cl_lock);
ret = nfsd4_free_lock_stateid(openlockstateid(s));
nfs4_put_stid(s);
ret = nfs_ok;
goto out;
case NFS4_REVOKED_DELEG_STID:
dp = delegstateid(s);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册