Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=fc1b356f566fe05929ec2a88ce2c7b15f8b6279f
Commit:     fc1b356f566fe05929ec2a88ce2c7b15f8b6279f
Parent:     07a2bf1da4765d987ffd1d8045e92ba032e0ad78
Author:     Trond Myklebust <[EMAIL PROTECTED]>
AuthorDate: Sat Jun 9 16:15:46 2007 -0400
Committer:  Trond Myklebust <[EMAIL PROTECTED]>
CommitDate: Tue Jul 10 23:40:34 2007 -0400

    SUNRPC: Fix races in rpcauth_create
    
    See the FIXME: auth_flavors[] really needs a lock and module refcounting.
    
    Signed-off-by: Trond Myklebust <[EMAIL PROTECTED]>
---
 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 f6b6c81..584f243 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -18,6 +18,7 @@
 # define RPCDBG_FACILITY       RPCDBG_AUTH
 #endif
 
+static DEFINE_SPINLOCK(rpc_authflavor_lock);
 static struct rpc_authops *    auth_flavors[RPC_AUTH_MAXFLAVOR] = {
        &authnull_ops,          /* AUTH_NULL */
        &authunix_ops,          /* AUTH_UNIX */
@@ -35,26 +36,34 @@ int
 rpcauth_register(struct rpc_authops *ops)
 {
        rpc_authflavor_t flavor;
+       int ret = -EPERM;
 
        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
                return -EINVAL;
-       if (auth_flavors[flavor] != NULL)
-               return -EPERM;          /* what else? */
-       auth_flavors[flavor] = ops;
-       return 0;
+       spin_lock(&rpc_authflavor_lock);
+       if (auth_flavors[flavor] == NULL) {
+               auth_flavors[flavor] = ops;
+               ret = 0;
+       }
+       spin_unlock(&rpc_authflavor_lock);
+       return ret;
 }
 
 int
 rpcauth_unregister(struct rpc_authops *ops)
 {
        rpc_authflavor_t flavor;
+       int ret = -EPERM;
 
        if ((flavor = ops->au_flavor) >= RPC_AUTH_MAXFLAVOR)
                return -EINVAL;
-       if (auth_flavors[flavor] != ops)
-               return -EPERM;          /* what else? */
-       auth_flavors[flavor] = NULL;
-       return 0;
+       spin_lock(&rpc_authflavor_lock);
+       if (auth_flavors[flavor] == ops) {
+               auth_flavors[flavor] = NULL;
+               ret = 0;
+       }
+       spin_unlock(&rpc_authflavor_lock);
+       return ret;
 }
 
 struct rpc_auth *
@@ -68,15 +77,19 @@ rpcauth_create(rpc_authflavor_t pseudoflavor, struct 
rpc_clnt *clnt)
        if (flavor >= RPC_AUTH_MAXFLAVOR)
                goto out;
 
-       /* FIXME - auth_flavors[] really needs an rw lock,
-        * and module refcounting. */
 #ifdef CONFIG_KMOD
        if ((ops = auth_flavors[flavor]) == NULL)
                request_module("rpc-auth-%u", flavor);
 #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;
+       }
+       spin_unlock(&rpc_authflavor_lock);
        auth = ops->create(clnt, pseudoflavor);
+       module_put(ops->owner);
        if (IS_ERR(auth))
                return auth;
        if (clnt->cl_auth)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to