summaryrefslogtreecommitdiff
path: root/security/apparmor/policy.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-12-11 11:18:45 -0200
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-12-11 11:18:45 -0200
commit9374020a78fce13a1cf2edf3d26f6dd7231b5c3d (patch)
tree50c8629e6c6222c5b9681506b52afbde818c5e56 /security/apparmor/policy.c
parentd2a0db1ee01aea154ccc460e45a16857e32c4427 (diff)
parent29594404d7fe73cd80eaa4ee8c43dcc53970c60e (diff)
Merge tag 'v3.7' into v4l_for_linus
Linux 3.7 * tag 'v3.7': (1545 commits) Linux 3.7 Input: matrix-keymap - provide proper module license Revert "revert "Revert "mm: remove __GFP_NO_KSWAPD""" and associated damage ipv4: ip_check_defrag must not modify skb before unsharing Revert "mm: avoid waking kswapd for THP allocations when compaction is deferred or contended" inet_diag: validate port comparison byte code to prevent unsafe reads inet_diag: avoid unsafe and nonsensical prefix matches in inet_diag_bc_run() inet_diag: validate byte code to prevent oops in inet_diag_bc_run() inet_diag: fix oops for IPv4 AF_INET6 TCP SYN-RECV state mm: vmscan: fix inappropriate zone congestion clearing vfs: fix O_DIRECT read past end of block device net: gro: fix possible panic in skb_gro_receive() tcp: bug fix Fast Open client retransmission tmpfs: fix shared mempolicy leak mm: vmscan: do not keep kswapd looping forever due to individual uncompactable zones mm: compaction: validate pfn range passed to isolate_freepages_block mmc: sh-mmcif: avoid oops on spurious interrupts (second try) Revert misapplied "mmc: sh-mmcif: avoid oops on spurious interrupts" mmc: sdhci-s3c: fix missing clock for gpio card-detect lib/Makefile: Fix oid_registry build dependency ...
Diffstat (limited to 'security/apparmor/policy.c')
-rw-r--r--security/apparmor/policy.c24
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:
*/
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);
}