projects/linux·commit fba3bad4

SUNRPC: Move upcall out of auth->au_ops->crcreate()

fba3bad4 · Trond Myklebust <[email protected]> · 2006-02-01 12:19:27 -05:00

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 <[email protected]>
Commit
fba3bad488a2eec2d76c067edb7a5ff92ef42431
Parents
adb12f63

Changes

3 files changed · +23 −9

FileStatusAddDelContent
include/linux/sunrpc/auth.hmodified+1−0View file
net/sunrpc/auth.cmodified+8−0View file
net/sunrpc/auth_gss/auth_gss.cmodified+14−9View file

include/linux/sunrpc/auth.h

View file
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index bfc5fb2..2647798 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);

net/sunrpc/auth.c

View file
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 1ca89c3..8d6f1a1 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;

net/sunrpc/auth_gss/auth_gss.c

View file
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 03affcb..bb46efd 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:
@@ -806,6 +797,19 @@ out_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)
{
struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
@@ -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,