diff mbox series

[SRU,B,v3,1/1] apparmor: Fix memory leak of profile proxy

Message ID 20210816175558.617474-3-georgia.garcia@canonical.com
State New
Headers show
Series [SRU,B,v3,1/1] apparmor: Fix memory leak of profile proxy | expand

Commit Message

Georgia Garcia Aug. 16, 2021, 5:55 p.m. UTC
From: John Johansen <john.johansen@canonical.com>

BugLink: https://bugs.launchpad.net/bugs/1939915

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>
(backported from commit 3622ad25d4d68fcbdef3bc084b5916873e785344)
Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
---
 security/apparmor/include/label.h |  1 +
 security/apparmor/label.c         | 19 +++++++------------
 security/apparmor/policy.c        |  1 +
 3 files changed, 9 insertions(+), 12 deletions(-)

Comments

Stefan Bader Aug. 19, 2021, 7:52 a.m. UTC | #1
On 16.08.21 19:55, Georgia Garcia wrote:
> From: John Johansen <john.johansen@canonical.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1939915
> 
> 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>
> (backported from commit 3622ad25d4d68fcbdef3bc084b5916873e785344)
> Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
> ---
>   security/apparmor/include/label.h |  1 +
>   security/apparmor/label.c         | 19 +++++++------------
>   security/apparmor/policy.c        |  1 +
>   3 files changed, 9 insertions(+), 12 deletions(-)
> 
> diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
> index af22dcbbcb8a..8ef94d6ffa09 100644
> --- a/security/apparmor/include/label.h
> +++ b/security/apparmor/include/label.h
> @@ -279,6 +279,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);
> diff --git a/security/apparmor/label.c b/security/apparmor/label.c
> index 9171cd8ec032..b5978f310ced 100644
> --- a/security/apparmor/label.c
> +++ b/security/apparmor/label.c
> @@ -313,10 +313,8 @@ int aa_vec_unique(struct aa_profile **vec, int n, int flags)
>   }
>   
>   
> -static void label_destroy(struct aa_label *label)
> +void aa_label_destroy(struct aa_label *label)
>   {
> -	struct aa_label *tmp;
> -
>   	AA_BUG(!label);
>   
>   	if (!label_isprofile(label)) {
> @@ -332,16 +330,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);
>   
> -	tmp = rcu_dereference_protected(label->proxy->label, true);
> -	if (tmp == label)
> -		rcu_assign_pointer(label->proxy->label, NULL);
> -

Instead of silently dropping these lines we should rather pick additionally

commit c84b80cd41e0
Author: Mateusz Nosek <mateusznosek0@gmail.com>
Date:   Tue Mar 3 19:30:23 2020 +0100

     security/apparmor/label.c: Clean code by removing redundant instructions

which does only that. There is a chance that this potentially allows to cherry 
pick the actual fix for Bionic as well. So

[SRU B/F] Fix memory leak...
+- [SRU B 1/2] security/apparmor/label.c: Clean code...
+- [SRU B 2/1, F 1/1] apparmor: Fix memory...


> >   	label->proxy = (struct aa_proxy *) PROXY_POISON + 1;
>   }
>   
> @@ -350,7 +345,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 a92c167c9249..1a7aa0ad5d0b 100644
> --- a/security/apparmor/policy.c
> +++ b/security/apparmor/policy.c
> @@ -240,6 +240,7 @@ void aa_free_profile(struct aa_profile *profile)
>   
>   	kzfree(profile->hash);
>   	aa_put_loaddata(profile->rawdata);
> +	aa_label_destroy(&profile->label);
>   
>   	kzfree(profile);
>   }
>
diff mbox series

Patch

diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
index af22dcbbcb8a..8ef94d6ffa09 100644
--- a/security/apparmor/include/label.h
+++ b/security/apparmor/include/label.h
@@ -279,6 +279,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);
diff --git a/security/apparmor/label.c b/security/apparmor/label.c
index 9171cd8ec032..b5978f310ced 100644
--- a/security/apparmor/label.c
+++ b/security/apparmor/label.c
@@ -313,10 +313,8 @@  int aa_vec_unique(struct aa_profile **vec, int n, int flags)
 }
 
 
-static void label_destroy(struct aa_label *label)
+void aa_label_destroy(struct aa_label *label)
 {
-	struct aa_label *tmp;
-
 	AA_BUG(!label);
 
 	if (!label_isprofile(label)) {
@@ -332,16 +330,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);
 
-	tmp = rcu_dereference_protected(label->proxy->label, true);
-	if (tmp == label)
-		rcu_assign_pointer(label->proxy->label, NULL);
-
-	aa_put_proxy(label->proxy);
 	label->proxy = (struct aa_proxy *) PROXY_POISON + 1;
 }
 
@@ -350,7 +345,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 a92c167c9249..1a7aa0ad5d0b 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -240,6 +240,7 @@  void aa_free_profile(struct aa_profile *profile)
 
 	kzfree(profile->hash);
 	aa_put_loaddata(profile->rawdata);
+	aa_label_destroy(&profile->label);
 
 	kzfree(profile);
 }