Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jmorris/linux-security

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
  • Loading branch information
Linus Torvalds committed Oct 24, 2012
2 parents 144d80b + 2e680dd commit 206aa6a
Showing 1 changed file with 23 additions and 1 deletion.
24 changes: 23 additions & 1 deletion security/apparmor/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,8 @@ struct aa_profile *aa_new_null_profile(struct aa_profile *parent, int hat)
*/
static void free_profile(struct aa_profile *profile)
{
struct aa_profile *p;

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

if (!profile)
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 206aa6a

Please sign in to comment.