]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
apparmor: Fix memory leak of profile proxy
authorJohn Johansen <john.johansen@canonical.com>
Sun, 7 Jun 2020 11:10:33 +0000 (04:10 -0700)
committerJohn Johansen <john.johansen@canonical.com>
Sun, 7 Jun 2020 20:38:55 +0000 (13:38 -0700)
When the proxy isn't replaced and the profile is removed, the proxy
is being leaked resulting in a kmemleak check message of

unreferenced object 0xffff888077a3a490 (size 16):
  comm "apparmor_parser", pid 128041, jiffies 4322684109 (age 1097.028s)
  hex dump (first 16 bytes):
    03 00 00 00 00 00 00 00 b0 92 fd 4b 81 88 ff ff  ...........K....
  backtrace:
    [<0000000084d5daf2>] aa_alloc_proxy+0x58/0xe0
    [<00000000ecc0e21a>] aa_alloc_profile+0x159/0x1a0
    [<000000004cc9ce15>] unpack_profile+0x275/0x1c40
    [<000000007332b3ca>] aa_unpack+0x1e7/0x7e0
    [<00000000e25e31bd>] aa_replace_profiles+0x18a/0x1d10
    [<00000000350d9415>] policy_update+0x237/0x650
    [<000000003fbf934e>] profile_load+0x122/0x160
    [<0000000047f7b781>] vfs_write+0x139/0x290
    [<000000008ad12358>] ksys_write+0xcd/0x170
    [<000000001a9daa7b>] do_syscall_64+0x70/0x310
    [<00000000b9efb0cf>] entry_SYSCALL_64_after_hwframe+0x49/0xb3

Make sure to cleanup the profile's embedded label which will result
on the proxy being properly freed.

Fixes: 637f688dc3dc ("apparmor: switch from profiles to using labels on contexts")
Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/include/label.h
security/apparmor/label.c
security/apparmor/policy.c

index 255764ab06e2f6ffb4d5f89ff560b85034afc2fd..1e90384b1523ac22bd3a7efd2855d61e19b68a40 100644 (file)
@@ -275,6 +275,7 @@ void aa_labelset_destroy(struct aa_labelset *ls);
 void aa_labelset_init(struct aa_labelset *ls);
 void __aa_labelset_update_subtree(struct aa_ns *ns);
 
+void aa_label_destroy(struct aa_label *label);
 void aa_label_free(struct aa_label *label);
 void aa_label_kref(struct kref *kref);
 bool aa_label_init(struct aa_label *label, int size, gfp_t gfp);
index 23f7a193df4f2d41ef033e97115c91620397d188..e68bcedca976b9340919216cfd7bdfa55deb268b 100644 (file)
@@ -309,7 +309,7 @@ out:
 }
 
 
-static void label_destroy(struct aa_label *label)
+void aa_label_destroy(struct aa_label *label)
 {
        AA_BUG(!label);
 
@@ -326,12 +326,13 @@ static void label_destroy(struct aa_label *label)
                }
        }
 
-       if (rcu_dereference_protected(label->proxy->label, true) == label)
-               rcu_assign_pointer(label->proxy->label, NULL);
-
+       if (label->proxy) {
+               if (rcu_dereference_protected(label->proxy->label, true) == label)
+                       rcu_assign_pointer(label->proxy->label, NULL);
+               aa_put_proxy(label->proxy);
+       }
        aa_free_secid(label->secid);
 
-       aa_put_proxy(label->proxy);
        label->proxy = (struct aa_proxy *) PROXY_POISON + 1;
 }
 
@@ -340,7 +341,7 @@ void aa_label_free(struct aa_label *label)
        if (!label)
                return;
 
-       label_destroy(label);
+       aa_label_destroy(label);
        kfree(label);
 }
 
index 269f2f53c0b115405eda0046249151b605d1d116..af4f50fda9e3023113210269277f779833b99cd6 100644 (file)
@@ -242,6 +242,7 @@ void aa_free_profile(struct aa_profile *profile)
 
        kzfree(profile->hash);
        aa_put_loaddata(profile->rawdata);
+       aa_label_destroy(&profile->label);
 
        kzfree(profile);
 }