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 931da57ad18798616be0a085957cc9d345a79ddc 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 6.1: 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 4ee5a450d118..a49d76192d4c 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -715,7 +715,7 @@ bool aa_current_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
*/
@@ -770,7 +770,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 24a0e23f1b2b..83d3d1e6d9dc 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c
@@ -53,8 +53,7 @@ void aa_secid_update(u32 secid, struct aa_label *label)
xa_unlock_irqrestore(&aa_secids, 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,87 @@
From 609c779bbec3bf8cfb91535b065495a8ec91d1a9 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>
Signed-off-by: Ben Hutchings <benh@debian.org>
---
security/apparmor/policy.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index a49d76192d4c..e51af2017888 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -251,6 +251,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
@@ -650,8 +651,9 @@ static int policy_ns_capable(struct aa_label *label,

/**
* aa_policy_view_capable - check if viewing policy in at @ns is allowed
- * label: label that is trying to view policy in ns
- * ns: namespace being viewed by @label (may be NULL if @label's ns)
+ * @label: label that is trying to view policy in ns
+ * @ns: namespace being viewed by @label (may be NULL if @label's ns)
+ *
* Returns: true if viewing policy is allowed
*
* If @ns is NULL then the namespace being viewed is assumed to be the
@@ -715,6 +717,7 @@ bool aa_current_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
@@ -826,11 +829,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,64 @@
From 05c8275824c0397544a6ac7c90ccda8eff4cef60 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. ]
---
security/apparmor/policy_unpack.c | 13 +++++++++++++
1 file changed, 13 insertions(+)

diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 17601235ff98..9fd5b76893d3 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -827,6 +827,13 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
if (!aa_unpack_u32(e, &profile->policy.start[0], "start"))
/* default start state */
profile->policy.start[0] = DFA_START;
+
+ const size_t 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] =
@@ -850,6 +857,12 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
if (!aa_unpack_u32(e, &profile->file.start, "dfa_start"))
/* default start state */
profile->file.start = DFA_START;
+
+ const size_t 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 1b595f1453b0229bb0e5784c72e36310bebd6069 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 9fd5b76893d3..b855522c729d 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -955,7 +955,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 (!aa_unpack_u32(e, &e->version, "version")) {
--
2.53.0

Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
From 07dd632e17a7204094a3041a722f3c01c70fba65 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 e51af2017888..27708f7ff33a 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
Loading