aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-06-09 16:15:46 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:34 -0400
commitfc1b356f566fe05929ec2a88ce2c7b15f8b6279f (patch)
tree7d790ea2d3618b9cb166081a86797411f3547e44 /net/sunrpc
parent07a2bf1da4765d987ffd1d8045e92ba032e0ad78 (diff)
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>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index f6b6c81cbc3e..584f24311a80 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -18,6 +18,7 @@
18# define RPCDBG_FACILITY RPCDBG_AUTH 18# define RPCDBG_FACILITY RPCDBG_AUTH
19#endif 19#endif
20 20
21static DEFINE_SPINLOCK(rpc_authflavor_lock);
21static struct rpc_authops * auth_flavors[RPC_AUTH_MAXFLAVOR] = { 22static struct rpc_authops * auth_flavors[RPC_AUTH_MAXFLAVOR] = {
22 &authnull_ops, /* AUTH_NULL */ 23 &authnull_ops, /* AUTH_NULL */
23 &authunix_ops, /* AUTH_UNIX */ 24 &authunix_ops, /* AUTH_UNIX */
@@ -35,26 +36,34 @@ int
35rpcauth_register(struct rpc_authops *ops) 36rpcauth_register(struct rpc_authops *ops)
36{ 37{
37 rpc_authflavor_t flavor; 38 rpc_authflavor_t flavor;
39 int ret = -EPERM;
38 40
39 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) 41 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
40 return -EINVAL; 42 return -EINVAL;
41 if (auth_flavors[flavor] != NULL) 43 spin_lock(&rpc_authflavor_lock);
42 return -EPERM; /* what else? */ 44 if (auth_flavors[flavor] == NULL) {
43 auth_flavors[flavor] = ops; 45 auth_flavors[flavor] = ops;
44 return 0; 46 ret = 0;
47 }
48 spin_unlock(&rpc_authflavor_lock);
49 return ret;
45} 50}
46 51
47int 52int
48rpcauth_unregister(struct rpc_authops *ops) 53rpcauth_unregister(struct rpc_authops *ops)
49{ 54{
50 rpc_authflavor_t flavor; 55 rpc_authflavor_t flavor;
56 int ret = -EPERM;
51 57
52 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR) 58 if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
53 return -EINVAL; 59 return -EINVAL;
54 if (auth_flavors[flavor] != ops) 60 spin_lock(&rpc_authflavor_lock);
55 return -EPERM; /* what else? */ 61 if (auth_flavors[flavor] == ops) {
56 auth_flavors[flavor] = NULL; 62 auth_flavors[flavor] = NULL;
57 return 0; 63 ret = 0;
64 }
65 spin_unlock(&rpc_authflavor_lock);
66 return ret;
58} 67}
59 68
60struct rpc_auth * 69struct rpc_auth *
@@ -68,15 +77,19 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct rpc_clnt *clnt)
68 if (flavor >= RPC_AUTH_MAXFLAVOR) 77 if (flavor >= RPC_AUTH_MAXFLAVOR)
69 goto out; 78 goto out;
70 79
71 /* FIXME - auth_flavors[] really needs an rw lock,
72 * and module refcounting. */
73#ifdef CONFIG_KMOD 80#ifdef CONFIG_KMOD
74 if ((ops = auth_flavors[flavor]) == NULL) 81 if ((ops = auth_flavors[flavor]) == NULL)
75 request_module("rpc-auth-%u", flavor); 82 request_module("rpc-auth-%u", flavor);
76#endif 83#endif
77 if ((ops = auth_flavors[flavor]) == NULL) 84 spin_lock(&rpc_authflavor_lock);
85 ops = auth_flavors[flavor];
86 if (ops == NULL || !try_module_get(ops->owner)) {
87 spin_unlock(&rpc_authflavor_lock);
78 goto out; 88 goto out;
89 }
90 spin_unlock(&rpc_authflavor_lock);
79 auth = ops->create(clnt, pseudoflavor); 91 auth = ops->create(clnt, pseudoflavor);
92 module_put(ops->owner);
80 if (IS_ERR(auth)) 93 if (IS_ERR(auth))
81 return auth; 94 return auth;
82 if (clnt->cl_auth) 95 if (clnt->cl_auth)