From: Trond Myklebust Date: Wed, 1 Feb 2006 17:19:27 +0000 (-0500) Subject: SUNRPC: Move upcall out of auth->au_ops->crcreate() X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=fba3bad488a2eec2d76c067edb7a5ff92ef42431;p=openwrt%2Fstaging%2Fblogic.git SUNRPC: Move upcall out of auth->au_ops->crcreate() This fixes a bug whereby if two processes try to look up the same auth_gss credential, they may end up creating two creds, and triggering two upcalls because the upcall is performed before the credential is added to the credcache. Signed-off-by: Trond Myklebust --- diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h index bfc5fb279539..2647798b72c7 100644 --- a/include/linux/sunrpc/auth.h +++ b/include/linux/sunrpc/auth.h @@ -110,6 +110,7 @@ struct rpc_authops { struct rpc_credops { const char * cr_name; /* Name of the auth flavour */ + int (*cr_init)(struct rpc_auth *, struct rpc_cred *); void (*crdestroy)(struct rpc_cred *); int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index 1ca89c36da7a..8d6f1a176b15 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c @@ -232,6 +232,14 @@ retry: goto retry; } else cred = new; + } else if ((cred->cr_flags & RPCAUTH_CRED_NEW) + && cred->cr_ops->cr_init != NULL + && !(flags & RPCAUTH_LOOKUP_NEW)) { + int res = cred->cr_ops->cr_init(auth, cred); + if (res < 0) { + put_rpccred(cred); + cred = ERR_PTR(res); + } } return (struct rpc_cred *) cred; diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 03affcbf6292..bb46efd92e57 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -788,15 +788,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) 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: @@ -805,6 +796,19 @@ out_err: return ERR_PTR(err); } +static int +gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) +{ + struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); + struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base); + int err; + + do { + err = gss_create_upcall(gss_auth, gss_cred); + } while (err == -EAGAIN); + return err; +} + static int gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) { @@ -1254,6 +1258,7 @@ static struct rpc_authops authgss_ops = { static struct rpc_credops gss_credops = { .cr_name = "AUTH_GSS", .crdestroy = gss_destroy_cred, + .cr_init = gss_cred_init, .crmatch = gss_match, .crmarshal = gss_marshal, .crrefresh = gss_refresh,