diff options
Diffstat (limited to 'security/apparmor/policy.c')
| -rw-r--r-- | security/apparmor/policy.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index cf5fd220309b..813200384d97 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
| @@ -724,6 +724,8 @@ fail: | |||
| 724 | */ | 724 | */ |
| 725 | static void free_profile(struct aa_profile *profile) | 725 | static void free_profile(struct aa_profile *profile) |
| 726 | { | 726 | { |
| 727 | struct aa_profile *p; | ||
| 728 | |||
| 727 | AA_DEBUG("%s(%p)\n", __func__, profile); | 729 | AA_DEBUG("%s(%p)\n", __func__, profile); |
| 728 | 730 | ||
| 729 | if (!profile) | 731 | if (!profile) |
| @@ -751,7 +753,27 @@ static void free_profile(struct aa_profile *profile) | |||
| 751 | aa_put_dfa(profile->xmatch); | 753 | aa_put_dfa(profile->xmatch); |
| 752 | aa_put_dfa(profile->policy.dfa); | 754 | aa_put_dfa(profile->policy.dfa); |
| 753 | 755 | ||
| 754 | aa_put_profile(profile->replacedby); | 756 | /* put the profile reference for replacedby, but not via |
| 757 | * put_profile(kref_put). | ||
| 758 | * replacedby can form a long chain that can result in cascading | ||
| 759 | * frees that blows the stack because kref_put makes a nested fn | ||
| 760 | * call (it looks like recursion, with free_profile calling | ||
| 761 | * free_profile) for each profile in the chain lp#1056078. | ||
| 762 | */ | ||
| 763 | for (p = profile->replacedby; p; ) { | ||
| 764 | if (atomic_dec_and_test(&p->base.count.refcount)) { | ||
| 765 | /* no more refs on p, grab its replacedby */ | ||
| 766 | struct aa_profile *next = p->replacedby; | ||
| 767 | /* break the chain */ | ||
| 768 | p->replacedby = NULL; | ||
| 769 | /* now free p, chain is broken */ | ||
| 770 | free_profile(p); | ||
| 771 | |||
| 772 | /* follow up with next profile in the chain */ | ||
| 773 | p = next; | ||
| 774 | } else | ||
| 775 | break; | ||
| 776 | } | ||
| 755 | 777 | ||
| 756 | kzfree(profile); | 778 | kzfree(profile); |
| 757 | } | 779 | } |
