Commit fba3bad4 authored by Trond Myklebust's avatar Trond Myklebust

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent adb12f63
...@@ -110,6 +110,7 @@ struct rpc_authops { ...@@ -110,6 +110,7 @@ struct rpc_authops {
struct rpc_credops { struct rpc_credops {
const char * cr_name; /* Name of the auth flavour */ const char * cr_name; /* Name of the auth flavour */
int (*cr_init)(struct rpc_auth *, struct rpc_cred *);
void (*crdestroy)(struct rpc_cred *); void (*crdestroy)(struct rpc_cred *);
int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
......
...@@ -232,6 +232,14 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, ...@@ -232,6 +232,14 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
goto retry; goto retry;
} else } else
cred = new; 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; return (struct rpc_cred *) cred;
......
...@@ -788,15 +788,6 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) ...@@ -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_ops = &gss_credops;
cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; cred->gc_base.cr_flags = RPCAUTH_CRED_NEW;
cred->gc_service = gss_auth->service; 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; return &cred->gc_base;
out_err: out_err:
...@@ -805,6 +796,19 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) ...@@ -805,6 +796,19 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
return ERR_PTR(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 static int
gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags)
{ {
...@@ -1254,6 +1258,7 @@ static struct rpc_authops authgss_ops = { ...@@ -1254,6 +1258,7 @@ static struct rpc_authops authgss_ops = {
static struct rpc_credops gss_credops = { static struct rpc_credops gss_credops = {
.cr_name = "AUTH_GSS", .cr_name = "AUTH_GSS",
.crdestroy = gss_destroy_cred, .crdestroy = gss_destroy_cred,
.cr_init = gss_cred_init,
.crmatch = gss_match, .crmatch = gss_match,
.crmarshal = gss_marshal, .crmarshal = gss_marshal,
.crrefresh = gss_refresh, .crrefresh = gss_refresh,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment