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 <Trond.Myklebust@netapp.com>
This commit is contained in:
Trond Myklebust 2006-02-01 12:19:27 -05:00
parent adb12f63e0
commit fba3bad488
3 changed files with 23 additions and 9 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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,