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

Commit 206aa6a6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull apparmor bugfix from James Morris.

Fix a possibly unbounded recursion by iterating over the entries instead.

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  apparmor: fix IRQ stack overflow during free_profile
parents 144d80be 2e680dd6
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -724,6 +724,8 @@ fail:
 */
static void free_profile(struct aa_profile *profile)
{
	struct aa_profile *p;

	AA_DEBUG("%s(%p)\n", __func__, profile);

	if (!profile)
@@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile)
	aa_put_dfa(profile->xmatch);
	aa_put_dfa(profile->policy.dfa);

	aa_put_profile(profile->replacedby);
	/* put the profile reference for replacedby, but not via
	 * put_profile(kref_put).
	 * replacedby can form a long chain that can result in cascading
	 * frees that blows the stack because kref_put makes a nested fn
	 * call (it looks like recursion, with free_profile calling
	 * free_profile) for each profile in the chain lp#1056078.
	 */
	for (p = profile->replacedby; p; ) {
		if (atomic_dec_and_test(&p->base.count.refcount)) {
			/* no more refs on p, grab its replacedby */
			struct aa_profile *next = p->replacedby;
			/* break the chain */
			p->replacedby = NULL;
			/* now free p, chain is broken */
			free_profile(p);

			/* follow up with next profile in the chain */
			p = next;
		} else
			break;
	}

	kzfree(profile);
}