Commit a4ee8d97 authored by Trond Myklebust's avatar Trond Myklebust

LOCKD: fix races in nsm_client_get

Commit e9406db2 (lockd: per-net
NSM client creation and destruction helpers introduced) contains
a nasty race on initialisation of the per-net NSM client because
it doesn't check whether or not the client is set after grabbing
the nsm_create_mutex.
Reported-by: default avatarNix <nix@esperi.org.uk>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
Cc: stable@vger.kernel.org
parent f878b657
...@@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net) ...@@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net)
return rpc_create(&args); return rpc_create(&args);
} }
static struct rpc_clnt *nsm_client_get(struct net *net) static struct rpc_clnt *nsm_client_set(struct lockd_net *ln,
struct rpc_clnt *clnt)
{ {
static DEFINE_MUTEX(nsm_create_mutex);
struct rpc_clnt *clnt;
struct lockd_net *ln = net_generic(net, lockd_net_id);
spin_lock(&ln->nsm_clnt_lock); spin_lock(&ln->nsm_clnt_lock);
if (ln->nsm_users) { if (ln->nsm_users == 0) {
ln->nsm_users++; if (clnt == NULL)
clnt = ln->nsm_clnt;
spin_unlock(&ln->nsm_clnt_lock);
goto out; goto out;
ln->nsm_clnt = clnt;
} }
clnt = ln->nsm_clnt;
ln->nsm_users++;
out:
spin_unlock(&ln->nsm_clnt_lock); spin_unlock(&ln->nsm_clnt_lock);
return clnt;
}
mutex_lock(&nsm_create_mutex); static struct rpc_clnt *nsm_client_get(struct net *net)
clnt = nsm_create(net); {
if (!IS_ERR(clnt)) { struct rpc_clnt *clnt, *new;
ln->nsm_clnt = clnt; struct lockd_net *ln = net_generic(net, lockd_net_id);
smp_wmb();
ln->nsm_users = 1; clnt = nsm_client_set(ln, NULL);
} if (clnt != NULL)
mutex_unlock(&nsm_create_mutex); goto out;
clnt = new = nsm_create(net);
if (IS_ERR(clnt))
goto out;
clnt = nsm_client_set(ln, new);
if (clnt != new)
rpc_shutdown_client(new);
out: out:
return clnt; return clnt;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment