Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+23 -9
+1
include/linux/sunrpc/auth.h
··· 110 110 111 111 struct rpc_credops { 112 112 const char * cr_name; /* Name of the auth flavour */ 113 + int (*cr_init)(struct rpc_auth *, struct rpc_cred *); 113 114 void (*crdestroy)(struct rpc_cred *); 114 115 115 116 int (*crmatch)(struct auth_cred *, struct rpc_cred *, int);
+8
net/sunrpc/auth.c
··· 232 232 goto retry; 233 233 } else 234 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 245 return (struct rpc_cred *) cred;
+14 -9
net/sunrpc/auth_gss/auth_gss.c
··· 788 788 cred->gc_base.cr_ops = &gss_credops; 789 789 cred->gc_base.cr_flags = RPCAUTH_CRED_NEW; 790 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 791 return &cred->gc_base; 801 792 802 793 out_err: 803 794 dprintk("RPC: gss_create_cred failed with error %d\n", err); 804 795 if (cred) gss_destroy_cred(&cred->gc_base); 805 796 return ERR_PTR(err); 797 + } 798 + 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; 806 810 } 807 811 808 812 static int ··· 1258 1254 static struct rpc_credops gss_credops = { 1259 1255 .cr_name = "AUTH_GSS", 1260 1256 .crdestroy = gss_destroy_cred, 1257 + .cr_init = gss_cred_init, 1261 1258 .crmatch = gss_match, 1262 1259 .crmarshal = gss_marshal, 1263 1260 .crrefresh = gss_refresh,