summaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/auth_gss.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-02-01 12:18:36 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-02-01 12:52:23 -0500
commit8a3177604b729ec3b80e43790ee978863ac7551b (patch)
tree6eeafbdae55e2b0821e524f2c16bca52fa150cdc /net/sunrpc/auth_gss/auth_gss.c
parentaaaa99423b4b1f9cfd33ea5643d9274c25f62491 (diff)
SUNRPC: Fix a lock recursion in the auth_gss downcall
When we look up a new cred in the auth_gss downcall so that we can stuff the credcache, we do not want that lookup to queue up an upcall in order to initialise it. To do an upcall here not only redundant, but since we are already holding the inode->i_mutex, it will trigger a lock recursion. This patch allows rpcauth cache searches to indicate that they can cope with uninitialised credentials. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/auth_gss/auth_gss.c')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c25
1 files changed, 19 insertions, 6 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 8d782282ec1..03affcbf629 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -158,6 +158,7 @@ gss_cred_set_ctx(struct rpc_cred *cred, struct gss_cl_ctx *ctx)
old = gss_cred->gc_ctx;
gss_cred->gc_ctx = ctx;
cred->cr_flags |= RPCAUTH_CRED_UPTODATE;
+ cred->cr_flags &= ~RPCAUTH_CRED_NEW;
write_unlock(&gss_ctx_lock);
if (old)
gss_put_ctx(old);
@@ -580,7 +581,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
} else {
struct auth_cred acred = { .uid = uid };
spin_unlock(&gss_auth->lock);
- cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0);
+ cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, RPCAUTH_LOOKUP_NEW);
if (IS_ERR(cred)) {
err = PTR_ERR(cred);
goto err_put_ctx;
@@ -758,13 +759,13 @@ gss_destroy_cred(struct rpc_cred *rc)
* Lookup RPCSEC_GSS cred for the current process
*/
static struct rpc_cred *
-gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
+gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
- return rpcauth_lookup_credcache(auth, acred, taskflags);
+ return rpcauth_lookup_credcache(auth, acred, flags);
}
static struct rpc_cred *
-gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
+gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
{
struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
struct gss_cred *cred = NULL;
@@ -785,13 +786,17 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
*/
cred->gc_flags = 0;
cred->gc_base.cr_ops = &gss_credops;
+ cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
cred->gc_service = gss_auth->service;
+ /* Is the caller prepared to initialise the credential? */
+ if (flags & RPCAUTH_LOOKUP_NEW)
+ goto out;
do {
err = gss_create_upcall(gss_auth, cred);
} while (err == -EAGAIN);
if (err < 0)
goto out_err;
-
+out:
return &cred->gc_base;
out_err:
@@ -801,13 +806,21 @@ out_err:
}
static int
-gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
+gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
{
struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
+ /*
+ * If the searchflags have set RPCAUTH_LOOKUP_NEW, then
+ * we don't really care if the credential has expired or not,
+ * since the caller should be prepared to reinitialise it.
+ */
+ if ((flags & RPCAUTH_LOOKUP_NEW) && (rc->cr_flags & RPCAUTH_CRED_NEW))
+ goto out;
/* Don't match with creds that have expired. */
if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
return 0;
+out:
return (rc->cr_uid == acred->uid);
}