diff options
author | John Johansen <john.johansen@canonical.com> | 2020-06-07 14:10:33 +0300 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2020-06-07 23:38:55 +0300 |
commit | 3622ad25d4d68fcbdef3bc084b5916873e785344 (patch) | |
tree | 02be80a4dfd2148fc252a9981bf9cd2cde8bd5d2 | |
parent | dd2569fbb053719f7df7ef8fdbb45cf47156a701 (diff) | |
download | linux-3622ad25d4d68fcbdef3bc084b5916873e785344.tar.xz |
apparmor: Fix memory leak of profile proxy
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>
-rw-r--r-- | security/apparmor/include/label.h | 1 | ||||
-rw-r--r-- | security/apparmor/label.c | 13 | ||||
-rw-r--r-- | security/apparmor/policy.c | 1 |
3 files changed, 9 insertions, 6 deletions
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h index 255764ab06e2..1e90384b1523 100644 --- a/security/apparmor/include/label.h +++ b/security/apparmor/include/label.h @@ -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); diff --git a/security/apparmor/label.c b/security/apparmor/label.c index 23f7a193df4f..e68bcedca976 100644 --- a/security/apparmor/label.c +++ b/security/apparmor/label.c @@ -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); } diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 269f2f53c0b1..af4f50fda9e3 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c @@ -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); } |