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 /net | |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/auth.c | 8 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 23 |
2 files changed, 22 insertions, 9 deletions
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, |