Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fba3bad4 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent adb12f63
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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;
+14 −9
Original line number Diff line number Diff line
@@ -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,