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:
parent
adb12f63e0
commit
fba3bad488
|
@ -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);
|
||||
|
|
|
@ -232,6 +232,14 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
|
|||
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;
|
||||
|
|
|
@ -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 @@ gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
|
|||
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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user