Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
From 96b5e706f89835e0956e8f87f764fd39c4a1912e Mon Sep 17 00:00:00 2001
From: Randy Dunlap <rdunlap@infradead.org>
Date: Mon, 2 Jan 2023 12:45:12 -0800
Subject: [PATCH 01/13] apparmor: fix kernel-doc complaints

commit 76862af5d1add618f0cc99868bc729925f9551d2 upstream.

Correct kernel-doc notation to placate kernel-doc W=1 warnings:

security/apparmor/policy.c:439: warning: duplicate section name 'Return'
security/apparmor/secid.c:57: warning: Cannot understand *
security/apparmor/file.c:174: warning: cannot understand function prototype: 'struct aa_perms default_perms = '

Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
Cc: John Johansen <john.johansen@canonical.com>
Cc: John Johansen <john@apparmor.net>
Cc: apparmor@lists.ubuntu.com
Cc: Paul Moore <paul@paul-moore.com>
Cc: James Morris <jmorris@namei.org>
Cc: "Serge E. Hallyn" <serge@hallyn.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
[bwh: Backported to 5.10: drop inapplicable changes]
Signed-off-by: Ben Hutchings <benh@debian.org>
---
security/apparmor/policy.c | 3 +--
security/apparmor/secid.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index e59bdb750ef0..b17ac2d7a670 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -674,7 +674,7 @@ bool policy_admin_capable(struct aa_ns *ns)
/**
* aa_may_manage_policy - can the current task manage policy
* @label: label to check if it can manage policy
- * @op: the policy manipulation operation being done
+ * @mask: contains the policy manipulation operation being done
*
* Returns: 0 if the task is allowed to manipulate policy else error
*/
@@ -729,7 +729,6 @@ static struct aa_profile *__list_lookup_parent(struct list_head *lh,
* __replace_profile - replace @old with @new on a list
* @old: profile to be replaced (NOT NULL)
* @new: profile to replace @old with (NOT NULL)
- * @share_proxy: transfer @old->proxy to @new
*
* Will duplicate and refcount elements that @new inherits from @old
* and will inherit @old children.
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c
index ce545f99259e..b85dfd343e7a 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c
@@ -52,8 +52,7 @@ void aa_secid_update(u32 secid, struct aa_label *label)
spin_unlock_irqrestore(&secid_lock, flags);
}

-/**
- *
+/*
* see label for inverse aa_label_to_secid
*/
struct aa_label *aa_secid_to_label(u32 secid)
--
2.53.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
From c988a0ed60fab11af1b1818696b3aca58f16e3bc Mon Sep 17 00:00:00 2001
From: Gaosheng Cui <cuigaosheng1@huawei.com>
Date: Sun, 25 Jun 2023 09:13:49 +0800
Subject: [PATCH 02/13] apparmor: Fix kernel-doc warnings in apparmor/policy.c

commit 25ff0ff2d6286928dc516c74b879809c691c2dd8 upstream.

Fix kernel-doc warnings:

security/apparmor/policy.c:294: warning: Function parameter or
member 'proxy' not described in 'aa_alloc_profile'
security/apparmor/policy.c:785: warning: Function parameter or
member 'label' not described in 'aa_policy_view_capable'
security/apparmor/policy.c:785: warning: Function parameter or
member 'ns' not described in 'aa_policy_view_capable'
security/apparmor/policy.c:847: warning: Function parameter or
member 'ns' not described in 'aa_may_manage_policy'
security/apparmor/policy.c:964: warning: Function parameter or
member 'hname' not described in '__lookup_replace'
security/apparmor/policy.c:964: warning: Function parameter or
member 'info' not described in '__lookup_replace'
security/apparmor/policy.c:964: warning: Function parameter or
member 'noreplace' not described in '__lookup_replace'
security/apparmor/policy.c:964: warning: Function parameter or
member 'ns' not described in '__lookup_replace'
security/apparmor/policy.c:964: warning: Function parameter or
member 'p' not described in '__lookup_replace'

Signed-off-by: Gaosheng Cui <cuigaosheng1@huawei.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
[bwh: Backported to 5.10: policy_view_capable() doesn't have a label parameter]
Signed-off-by: Ben Hutchings <benh@debian.org>
---
security/apparmor/policy.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index b17ac2d7a670..ef85a5d46640 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -250,6 +250,7 @@ void aa_free_profile(struct aa_profile *profile)
/**
* aa_alloc_profile - allocate, initialize and return a new profile
* @hname: name of the profile (NOT NULL)
+ * @proxy: proxy to use OR null if to allocate a new one
* @gfp: allocation type
*
* Returns: refcount profile or NULL on failure
@@ -634,7 +635,8 @@ static int audit_policy(struct aa_label *label, const char *op,

/**
* policy_view_capable - check if viewing policy in at @ns is allowed
- * ns: namespace being viewed by current task (may be NULL)
+ * @ns: namespace being viewed by current task (may be NULL)
+ *
* Returns: true if viewing policy is allowed
*
* If @ns is NULL then the namespace being viewed is assumed to be the
@@ -674,6 +676,7 @@ bool policy_admin_capable(struct aa_ns *ns)
/**
* aa_may_manage_policy - can the current task manage policy
* @label: label to check if it can manage policy
+ * @ns: namespace being managed by @label (may be NULL if @label's ns)
* @mask: contains the policy manipulation operation being done
*
* Returns: 0 if the task is allowed to manipulate policy else error
@@ -785,11 +788,11 @@ static void __replace_profile(struct aa_profile *old, struct aa_profile *new)

/**
* __lookup_replace - lookup replacement information for a profile
- * @ns - namespace the lookup occurs in
- * @hname - name of profile to lookup
- * @noreplace - true if not replacing an existing profile
- * @p - Returns: profile to be replaced
- * @info - Returns: info string on why lookup failed
+ * @ns: namespace the lookup occurs in
+ * @hname: name of profile to lookup
+ * @noreplace: true if not replacing an existing profile
+ * @p: Returns - profile to be replaced
+ * @info: Returns - info string on why lookup failed
*
* Returns: profile to replace (no ref) on success else ptr error
*/
--
2.53.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
From c1dd0ceaf206a2230d1a0a6a12ad411bf2645d1d Mon Sep 17 00:00:00 2001
From: Massimiliano Pellizzer <massimiliano.pellizzer@canonical.com>
Date: Thu, 15 Jan 2026 15:30:50 +0100
Subject: [PATCH 03/13] apparmor: validate DFA start states are in bounds in
unpack_pdb

Start states are read from untrusted data and used as indexes into the
DFA state tables. The aa_dfa_next() function call in unpack_pdb() will
access dfa->tables[YYTD_ID_BASE][start], and if the start state exceeds
the number of states in the DFA, this results in an out-of-bound read.

==================================================================
BUG: KASAN: slab-out-of-bounds in aa_dfa_next+0x2a1/0x360
Read of size 4 at addr ffff88811956fb90 by task su/1097
...

Reject policies with out-of-bounds start states during unpacking
to prevent the issue.

Reported-by: Qualys Security Advisory <qsa@qualys.com>
Fixes: ad5ff3db53c6 ("AppArmor: Add ability to load extended policy")
Signed-off-by: Massimiliano Pellizzer <massimiliano.pellizzer@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
[ Salvatore Bonaccorso: Apply backported change as proposed by Qualys
Security Advisory Team for 6.1.y series without ad596ea74e74 ("apparmor:
group dfa policydb unpacking") introduced in v6.2-rc1. ]
[bwh: Backported to 5.10: separate declaration and initialisation
of state_count since we build with -std=gnu89]
Signed-off-by: Ben Hutchings <benh@debian.org>
---
security/apparmor/policy_unpack.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)

diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 93fcafdaa548..4b242d071435 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -830,6 +830,8 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
}

if (unpack_nameX(e, AA_STRUCT, "policydb")) {
+ size_t state_count;
+
/* generic policy dfa - optional and may be NULL */
info = "failed to unpack policydb";
profile->policy.dfa = unpack_dfa(e);
@@ -844,6 +846,13 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
if (!unpack_u32(e, &profile->policy.start[0], "start"))
/* default start state */
profile->policy.start[0] = DFA_START;
+
+ state_count = profile->policy.dfa->tables[YYTD_ID_BASE]->td_lolen;
+ if (profile->policy.start[0] >= state_count) {
+ info = "invalid policy dfa start state";
+ goto fail;
+ }
+
/* setup class index */
for (i = AA_CLASS_FILE; i <= AA_CLASS_LAST; i++) {
profile->policy.start[i] =
@@ -864,9 +873,17 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
info = "failed to unpack profile file rules";
goto fail;
} else if (profile->file.dfa) {
+ size_t state_count;
+
if (!unpack_u32(e, &profile->file.start, "dfa_start"))
/* default start state */
profile->file.start = DFA_START;
+
+ state_count = profile->file.dfa->tables[YYTD_ID_BASE]->td_lolen;
+ if (profile->file.start >= state_count) {
+ info = "invalid file dfa start state";
+ goto fail;
+ }
} else if (profile->policy.dfa &&
profile->policy.start[AA_CLASS_FILE]) {
profile->file.dfa = aa_get_dfa(profile->policy.dfa);
--
2.53.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
From 41f9c907911f93cef85dde0e45ce3cb71934fed8 Mon Sep 17 00:00:00 2001
From: Massimiliano Pellizzer <massimiliano.pellizzer@canonical.com>
Date: Tue, 20 Jan 2026 15:24:04 +0100
Subject: [PATCH 04/13] apparmor: fix memory leak in verify_header

The function sets `*ns = NULL` on every call, leaking the namespace
string allocated in previous iterations when multiple profiles are
unpacked. This also breaks namespace consistency checking since *ns
is always NULL when the comparison is made.

Remove the incorrect assignment.
The caller (aa_unpack) initializes *ns to NULL once before the loop,
which is sufficient.

Fixes: dd51c8485763 ("apparmor: provide base for multiple profiles to be replaced at once")
Reported-by: Qualys Security Advisory <qsa@qualys.com>
Tested-by: Salvatore Bonaccorso <carnil@debian.org>
Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com>
Reviewed-by: Cengiz Can <cengiz.can@canonical.com>
Signed-off-by: Massimiliano Pellizzer <massimiliano.pellizzer@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/policy_unpack.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 4b242d071435..8380e64ccd72 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -976,7 +976,6 @@ static int verify_header(struct aa_ext *e, int required, const char **ns)
{
int error = -EPROTONOSUPPORT;
const char *name = NULL;
- *ns = NULL;

/* get the interface version */
if (!unpack_u32(e, &e->version, "version")) {
--
2.53.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
From 9b6e087e1263e04523ec7b747eaf56770e5e689a Mon Sep 17 00:00:00 2001
From: Massimiliano Pellizzer <massimiliano.pellizzer@canonical.com>
Date: Tue, 13 Jan 2026 09:09:43 +0100
Subject: [PATCH 05/13] apparmor: replace recursive profile removal with
iterative approach

The profile removal code uses recursion when removing nested profiles,
which can lead to kernel stack exhaustion and system crashes.

Reproducer:
$ pf='a'; for ((i=0; i<1024; i++)); do
echo -e "profile $pf { \n }" | apparmor_parser -K -a;
pf="$pf//x";
done
$ echo -n a > /sys/kernel/security/apparmor/.remove

Replace the recursive __aa_profile_list_release() approach with an
iterative approach in __remove_profile(). The function repeatedly
finds and removes leaf profiles until the entire subtree is removed,
maintaining the same removal semantic without recursion.

Fixes: c88d4c7b049e ("AppArmor: core policy routines")
Reported-by: Qualys Security Advisory <qsa@qualys.com>
Tested-by: Salvatore Bonaccorso <carnil@debian.org>
Reviewed-by: Georgia Garcia <georgia.garcia@canonical.com>
Reviewed-by: Cengiz Can <cengiz.can@canonical.com>
Signed-off-by: Massimiliano Pellizzer <massimiliano.pellizzer@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
---
security/apparmor/policy.c | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)

diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index ef85a5d46640..9f1fca42c2c8 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -146,19 +146,43 @@ static void __list_remove_profile(struct aa_profile *profile)
}

/**
- * __remove_profile - remove old profile, and children
- * @profile: profile to be replaced (NOT NULL)
+ * __remove_profile - remove profile, and children
+ * @profile: profile to be removed (NOT NULL)
*
* Requires: namespace list lock be held, or list not be shared
*/
static void __remove_profile(struct aa_profile *profile)
{
+ struct aa_profile *curr, *to_remove;
+
AA_BUG(!profile);
AA_BUG(!profile->ns);
AA_BUG(!mutex_is_locked(&profile->ns->lock));

/* release any children lists first */
- __aa_profile_list_release(&profile->base.profiles);
+ if (!list_empty(&profile->base.profiles)) {
+ curr = list_first_entry(&profile->base.profiles, struct aa_profile, base.list);
+
+ while (curr != profile) {
+
+ while (!list_empty(&curr->base.profiles))
+ curr = list_first_entry(&curr->base.profiles,
+ struct aa_profile, base.list);
+
+ to_remove = curr;
+ if (!list_is_last(&to_remove->base.list,
+ &aa_deref_parent(curr)->base.profiles))
+ curr = list_next_entry(to_remove, base.list);
+ else
+ curr = aa_deref_parent(curr);
+
+ /* released by free_profile */
+ aa_label_remove(&to_remove->label);
+ __aafs_profile_rmdir(to_remove);
+ __list_remove_profile(to_remove);
+ }
+ }
+
/* released by free_profile */
aa_label_remove(&profile->label);
__aafs_profile_rmdir(profile);
--
2.53.0

Loading