mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
SUNRPC: Fix races in rpcauth_create
See the FIXME: auth_flavors[] really needs a lock and module refcounting. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
This commit is contained in:
parent
07a2bf1da4
commit
fc1b356f56
@ -18,6 +18,7 @@
|
|||||||
# define RPCDBG_FACILITY RPCDBG_AUTH
|
# define RPCDBG_FACILITY RPCDBG_AUTH
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(rpc_authflavor_lock);
|
||||||
static struct rpc_authops * auth_flavors[RPC_AUTH_MAXFLAVOR] = {
|
static struct rpc_authops * auth_flavors[RPC_AUTH_MAXFLAVOR] = {
|
||||||
&authnull_ops, /* AUTH_NULL */
|
&authnull_ops, /* AUTH_NULL */
|
||||||
&authunix_ops, /* AUTH_UNIX */
|
&authunix_ops, /* AUTH_UNIX */
|
||||||
@ -35,26 +36,34 @@ int
|
|||||||
rpcauth_register(struct rpc_authops *ops)
|
rpcauth_register(struct rpc_authops *ops)
|
||||||
{
|
{
|
||||||
rpc_authflavor_t flavor;
|
rpc_authflavor_t flavor;
|
||||||
|
int ret = -EPERM;
|
||||||
|
|
||||||
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (auth_flavors[flavor] != NULL)
|
spin_lock(&rpc_authflavor_lock);
|
||||||
return -EPERM; /* what else? */
|
if (auth_flavors[flavor] == NULL) {
|
||||||
auth_flavors[flavor] = ops;
|
auth_flavors[flavor] = ops;
|
||||||
return 0;
|
ret = 0;
|
||||||
|
}
|
||||||
|
spin_unlock(&rpc_authflavor_lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
rpcauth_unregister(struct rpc_authops *ops)
|
rpcauth_unregister(struct rpc_authops *ops)
|
||||||
{
|
{
|
||||||
rpc_authflavor_t flavor;
|
rpc_authflavor_t flavor;
|
||||||
|
int ret = -EPERM;
|
||||||
|
|
||||||
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (auth_flavors[flavor] != ops)
|
spin_lock(&rpc_authflavor_lock);
|
||||||
return -EPERM; /* what else? */
|
if (auth_flavors[flavor] == ops) {
|
||||||
auth_flavors[flavor] = NULL;
|
auth_flavors[flavor] = NULL;
|
||||||
return 0;
|
ret = 0;
|
||||||
|
}
|
||||||
|
spin_unlock(&rpc_authflavor_lock);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rpc_auth *
|
struct rpc_auth *
|
||||||
@ -68,15 +77,19 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
|
|||||||
if (flavor >= RPC_AUTH_MAXFLAVOR)
|
if (flavor >= RPC_AUTH_MAXFLAVOR)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* FIXME - auth_flavors[] really needs an rw lock,
|
|
||||||
* and module refcounting. */
|
|
||||||
#ifdef CONFIG_KMOD
|
#ifdef CONFIG_KMOD
|
||||||
if ((ops = auth_flavors[flavor]) == NULL)
|
if ((ops = auth_flavors[flavor]) == NULL)
|
||||||
request_module("rpc-auth-%u", flavor);
|
request_module("rpc-auth-%u", flavor);
|
||||||
#endif
|
#endif
|
||||||
if ((ops = auth_flavors[flavor]) == NULL)
|
spin_lock(&rpc_authflavor_lock);
|
||||||
|
ops = auth_flavors[flavor];
|
||||||
|
if (ops == NULL || !try_module_get(ops->owner)) {
|
||||||
|
spin_unlock(&rpc_authflavor_lock);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
spin_unlock(&rpc_authflavor_lock);
|
||||||
auth = ops->create(clnt, pseudoflavor);
|
auth = ops->create(clnt, pseudoflavor);
|
||||||
|
module_put(ops->owner);
|
||||||
if (IS_ERR(auth))
|
if (IS_ERR(auth))
|
||||||
return auth;
|
return auth;
|
||||||
if (clnt->cl_auth)
|
if (clnt->cl_auth)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user