diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-06-09 16:15:46 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-07-10 23:40:34 -0400 |
commit | fc1b356f566fe05929ec2a88ce2c7b15f8b6279f (patch) | |
tree | 7d790ea2d3618b9cb166081a86797411f3547e44 /net/sunrpc | |
parent | 07a2bf1da4765d987ffd1d8045e92ba032e0ad78 (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.c | 35 |
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 | ||
21 | static DEFINE_SPINLOCK(rpc_authflavor_lock); | ||
21 | static struct rpc_authops * auth_flavors[RPC_AUTH_MAXFLAVOR] = { | 22 | static 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 | |||
35 | rpcauth_register(struct rpc_authops *ops) | 36 | rpcauth_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 | ||
47 | int | 52 | int |
48 | rpcauth_unregister(struct rpc_authops *ops) | 53 | rpcauth_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 | ||
60 | struct rpc_auth * | 69 | struct 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) |