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

Commit 3ab9bb72 authored by Trond Myklebust's avatar Trond Myklebust
Browse files

SUNRPC: Fix a memory leak in the auth credcache code



The leak only affects the RPCSEC_GSS caches, since they are the only ones
that are dynamically allocated...
Rename the existing rpcauth_free_credcache() to rpcauth_clear_credcache()
in order to better describe its role, then add a new function
rpcauth_destroy_credcache() that actually frees the cache in addition to
clearing it out.

Also move the call to destroy the credcache in gss_destroy() to come before
the rpc upcall pipe is unlinked.

Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 03a1256f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -143,7 +143,8 @@ int rpcauth_refreshcred(struct rpc_task *);
void			rpcauth_invalcred(struct rpc_task *);
int			rpcauth_uptodatecred(struct rpc_task *);
int			rpcauth_init_credcache(struct rpc_auth *, unsigned long);
void			rpcauth_free_credcache(struct rpc_auth *);
void			rpcauth_destroy_credcache(struct rpc_auth *);
void			rpcauth_clear_credcache(struct rpc_cred_cache *);

static inline
struct rpc_cred *	get_rpccred(struct rpc_cred *cred)
+16 −2
Original line number Diff line number Diff line
@@ -137,9 +137,8 @@ void rpcauth_destroy_credlist(struct hlist_head *head)
 * that are not referenced.
 */
void
rpcauth_free_credcache(struct rpc_auth *auth)
rpcauth_clear_credcache(struct rpc_cred_cache *cache)
{
	struct rpc_cred_cache *cache = auth->au_credcache;
	HLIST_HEAD(free);
	struct hlist_node *pos, *next;
	struct rpc_cred	*cred;
@@ -157,6 +156,21 @@ rpcauth_free_credcache(struct rpc_auth *auth)
	rpcauth_destroy_credlist(&free);
}

/*
 * Destroy the RPC credential cache
 */
void
rpcauth_destroy_credcache(struct rpc_auth *auth)
{
	struct rpc_cred_cache *cache = auth->au_credcache;

	if (cache) {
		auth->au_credcache = NULL;
		rpcauth_clear_credcache(cache);
		kfree(cache);
	}
}

static void
rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
{
+2 −1
Original line number Diff line number Diff line
@@ -665,12 +665,13 @@ gss_destroy(struct rpc_auth *auth)
	dprintk("RPC:       destroying GSS authenticator %p flavor %d\n",
			auth, auth->au_flavor);

	rpcauth_destroy_credcache(auth);

	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
	rpc_unlink(gss_auth->dentry);
	gss_auth->dentry = NULL;
	gss_mech_put(gss_auth->mech);

	rpcauth_free_credcache(auth);
	kfree(gss_auth);
	module_put(THIS_MODULE);
}
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ static void
unx_destroy(struct rpc_auth *auth)
{
	dprintk("RPC:       destroying UNIX authenticator %p\n", auth);
	rpcauth_free_credcache(auth);
	rpcauth_clear_credcache(auth->au_credcache);
}

/*
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ EXPORT_SYMBOL(rpcauth_unregister);
EXPORT_SYMBOL(rpcauth_create);
EXPORT_SYMBOL(rpcauth_lookupcred);
EXPORT_SYMBOL(rpcauth_lookup_credcache);
EXPORT_SYMBOL(rpcauth_free_credcache);
EXPORT_SYMBOL(rpcauth_destroy_credcache);
EXPORT_SYMBOL(rpcauth_init_credcache);
EXPORT_SYMBOL(put_rpccred);