diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-02-01 12:19:27 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-02-01 12:52:25 -0500 |
| commit | fba3bad488a2eec2d76c067edb7a5ff92ef42431 (patch) | |
| tree | a7cee933e9089e5c187008b396ee7bcbdb57ff80 | |
| parent | adb12f63e0f837078c6832fa2c90649ddeaab54f (diff) | |
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>
| -rw-r--r-- | include/linux/sunrpc/auth.h | 1 | ||||
| -rw-r--r-- | net/sunrpc/auth.c | 8 | ||||
| -rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 23 |
3 files changed, 23 insertions, 9 deletions
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 { | |||
| 110 | 110 | ||
| 111 | struct rpc_credops { | 111 | struct rpc_credops { |
| 112 | const char * cr_name; /* Name of the auth flavour */ | 112 | const char * cr_name; /* Name of the auth flavour */ |
| 113 | int (*cr_init)(struct rpc_auth *, struct rpc_cred *); | ||
| 113 | void (*crdestroy)(struct rpc_cred *); | 114 | void (*crdestroy)(struct rpc_cred *); |
| 114 | 115 | ||
| 115 | int (*crmatch)(struct auth_cred *, struct rpc_cred *, int); | 116 | 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: | |||
| 232 | goto retry; | 232 | goto retry; |
| 233 | } else | 233 | } else |
| 234 | cred = new; | 234 | cred = new; |
| 235 | } else if ((cred->cr_flags & RPCAUTH_CRED_NEW) | ||
| 236 | && cred->cr_ops->cr_init != NULL | ||
| 237 | && !(flags & RPCAUTH_LOOKUP_NEW)) { | ||
| 238 | int res = cred->cr_ops->cr_init(auth, cred); | ||
| 239 | if (res < 0) { | ||
| 240 | put_rpccred(cred); | ||
| 241 | cred = ERR_PTR(res); | ||
| 242 | } | ||
| 235 | } | 243 | } |
| 236 | 244 | ||
| 237 | return (struct rpc_cred *) cred; | 245 | 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) | |||
| 788 | cred->gc_base.cr_ops = &gss_credops; | 788 | cred->gc_base.cr_ops = &gss_credops; |
| 789 | cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; | 789 | cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; |
| 790 | cred->gc_service = gss_auth->service; | 790 | cred->gc_service = gss_auth->service; |
| 791 | /* Is the caller prepared to initialise the credential? */ | ||
| 792 | if (flags & RPCAUTH_LOOKUP_NEW) | ||
| 793 | goto out; | ||
| 794 | do { | ||
| 795 | err = gss_create_upcall(gss_auth, cred); | ||
| 796 | } while (err == -EAGAIN); | ||
| 797 | if (err < 0) | ||
| 798 | goto out_err; | ||
| 799 | out: | ||
| 800 | return &cred->gc_base; | 791 | return &cred->gc_base; |
| 801 | 792 | ||
| 802 | out_err: | 793 | out_err: |
| @@ -806,6 +797,19 @@ out_err: | |||
| 806 | } | 797 | } |
| 807 | 798 | ||
| 808 | static int | 799 | static int |
| 800 | gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) | ||
| 801 | { | ||
| 802 | struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth); | ||
| 803 | struct gss_cred *gss_cred = container_of(cred,struct gss_cred, gc_base); | ||
| 804 | int err; | ||
| 805 | |||
| 806 | do { | ||
| 807 | err = gss_create_upcall(gss_auth, gss_cred); | ||
| 808 | } while (err == -EAGAIN); | ||
| 809 | return err; | ||
| 810 | } | ||
| 811 | |||
| 812 | static int | ||
| 809 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | 813 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) |
| 810 | { | 814 | { |
| 811 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 815 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
| @@ -1254,6 +1258,7 @@ static struct rpc_authops authgss_ops = { | |||
| 1254 | static struct rpc_credops gss_credops = { | 1258 | static struct rpc_credops gss_credops = { |
| 1255 | .cr_name = "AUTH_GSS", | 1259 | .cr_name = "AUTH_GSS", |
| 1256 | .crdestroy = gss_destroy_cred, | 1260 | .crdestroy = gss_destroy_cred, |
| 1261 | .cr_init = gss_cred_init, | ||
| 1257 | .crmatch = gss_match, | 1262 | .crmatch = gss_match, |
| 1258 | .crmarshal = gss_marshal, | 1263 | .crmarshal = gss_marshal, |
| 1259 | .crrefresh = gss_refresh, | 1264 | .crrefresh = gss_refresh, |
