<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-stable.git/security/apparmor/task.c, branch v6.18.50</title>
<subtitle>Linux kernel stable tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/'/>
<entry>
<title>apparmor: fix cred UAF caused by begin_current_label_crit_section()</title>
<updated>2026-09-07T15:22:21+00:00</updated>
<author>
<name>Jann Horn</name>
<email>jannh@google.com</email>
</author>
<published>2026-08-06T15:55:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=587a6a92b93ec314c583bbf747413af170d42540'/>
<id>587a6a92b93ec314c583bbf747413af170d42540</id>
<content type='text'>
commit 3f4ae5fab613dca01d6a2a8210dd832e009fcf47 upstream.

AppArmor's begin_current_label_crit_section() is a scary function called
from lots of LSM hooks (in particular VFS/socket-related ones) that checks
if the label referenced by the current creds is marked FLAG_STALE, and if
so, attempts to use aa_replace_current_label() to replace the creds with an
updated version that uses a new label.

The first problem with this is that it would directly lead to UAF of
`struct cred` if anything in the kernel takes a pointer to the current
creds and accesses these past a security hook invocation that replaces
creds, like so:
```
const struct cred *cred = current_cred();
alloc_file_pseudo(...);
uid_t uid = cred-&gt;euid;
```
I don't know if anything in the kernel actually does this, but I think it
is very surprising that this pattern could lead to UAF.

The second problem is that things go wrong when aa_replace_current_label()
runs with overridden credentials. aa_replace_current_label() bails out if
`current_cred() != current_real_cred()` (mirroring the check in
proc_pid_attr_write()), but this check can't actually reliably detect
overridden credentials because the overridden creds can be the same as the
objective creds.

So in approximately the following scenario, things go wrong:

1. task begins with &lt;creds A&gt; (as both objective and subjective creds),
   with refcount=2
2. task grabs an extra reference on &lt;creds A&gt; for overriding
3. task calls override_creds(&lt;creds A&gt;), which returns a pointer to the old
   subjective creds (&lt;creds A&gt;)
4. task enters AppArmor LSM hook
5. AppArmor checks that objective/subjective creds are equal
6. AppArmor replaces both cred pointers with &lt;creds B&gt; and drops 2 refs on
   &lt;creds A&gt;
7. task leaves AppArmor LSM hook
8. task calls revert_creds(&lt;creds A&gt;)
9. now task-&gt;cred is &lt;creds A&gt; while task-&gt;real_cred is &lt;creds B&gt;, but the
   task_struct logically holds two references to &lt;creds B&gt;
10. another task drops the extra reference on &lt;creds A&gt; that was used for
    overriding, refcount drops to 0
11. now task-&gt;real_cred points to freed creds

At this point, any access to current_cred() will be UAF.

I have a test case where I run aa-disable on a profile while a process
using that profile is blocked on splice() from a FUSE passthrough file into
a full pipe; after the profile update, the pipe becomes empty, splice()
resumes, the credentials go out of sync, and a subsequent getuid() syscall
results in a KASAN UAF splat.

To fix this, instead of directly replacing creds, do it via task_work that
will run at the end of the current syscall. (The point in time at which the
cred replacement happens should have no correctness impact; it is just a
performance optimization to avoid unnecessarily touching the refcount of
the new label.)

Note that AppArmor still performs direct cred replacements in the
sb_pivotroot LSM hook after this change, and that direct cred replacements
can still happen in VFS -&gt;write() callbacks via proc_pid_attr_write().

There are two options for what to do with aa_dup_task_ctx(): Either
explicitly reset new-&gt;label_replacement_pending after the entire
aa_task_ctx has been copied, or switch to manually copying members over.
I am switching to manually copying members over because that should make
bugs more obvious.

Cc: stable@vger.kernel.org
Fixes: c75afcd153f6 ("AppArmor: contexts used in attaching policy to system objects")
Signed-off-by: Jann Horn &lt;jannh@google.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit 3f4ae5fab613dca01d6a2a8210dd832e009fcf47 upstream.

AppArmor's begin_current_label_crit_section() is a scary function called
from lots of LSM hooks (in particular VFS/socket-related ones) that checks
if the label referenced by the current creds is marked FLAG_STALE, and if
so, attempts to use aa_replace_current_label() to replace the creds with an
updated version that uses a new label.

The first problem with this is that it would directly lead to UAF of
`struct cred` if anything in the kernel takes a pointer to the current
creds and accesses these past a security hook invocation that replaces
creds, like so:
```
const struct cred *cred = current_cred();
alloc_file_pseudo(...);
uid_t uid = cred-&gt;euid;
```
I don't know if anything in the kernel actually does this, but I think it
is very surprising that this pattern could lead to UAF.

The second problem is that things go wrong when aa_replace_current_label()
runs with overridden credentials. aa_replace_current_label() bails out if
`current_cred() != current_real_cred()` (mirroring the check in
proc_pid_attr_write()), but this check can't actually reliably detect
overridden credentials because the overridden creds can be the same as the
objective creds.

So in approximately the following scenario, things go wrong:

1. task begins with &lt;creds A&gt; (as both objective and subjective creds),
   with refcount=2
2. task grabs an extra reference on &lt;creds A&gt; for overriding
3. task calls override_creds(&lt;creds A&gt;), which returns a pointer to the old
   subjective creds (&lt;creds A&gt;)
4. task enters AppArmor LSM hook
5. AppArmor checks that objective/subjective creds are equal
6. AppArmor replaces both cred pointers with &lt;creds B&gt; and drops 2 refs on
   &lt;creds A&gt;
7. task leaves AppArmor LSM hook
8. task calls revert_creds(&lt;creds A&gt;)
9. now task-&gt;cred is &lt;creds A&gt; while task-&gt;real_cred is &lt;creds B&gt;, but the
   task_struct logically holds two references to &lt;creds B&gt;
10. another task drops the extra reference on &lt;creds A&gt; that was used for
    overriding, refcount drops to 0
11. now task-&gt;real_cred points to freed creds

At this point, any access to current_cred() will be UAF.

I have a test case where I run aa-disable on a profile while a process
using that profile is blocked on splice() from a FUSE passthrough file into
a full pipe; after the profile update, the pipe becomes empty, splice()
resumes, the credentials go out of sync, and a subsequent getuid() syscall
results in a KASAN UAF splat.

To fix this, instead of directly replacing creds, do it via task_work that
will run at the end of the current syscall. (The point in time at which the
cred replacement happens should have no correctness impact; it is just a
performance optimization to avoid unnecessarily touching the refcount of
the new label.)

Note that AppArmor still performs direct cred replacements in the
sb_pivotroot LSM hook after this change, and that direct cred replacements
can still happen in VFS -&gt;write() callbacks via proc_pid_attr_write().

There are two options for what to do with aa_dup_task_ctx(): Either
explicitly reset new-&gt;label_replacement_pending after the entire
aa_task_ctx has been copied, or switch to manually copying members over.
I am switching to manually copying members over because that should make
bugs more obvious.

Cc: stable@vger.kernel.org
Fixes: c75afcd153f6 ("AppArmor: contexts used in attaching policy to system objects")
Signed-off-by: Jann Horn &lt;jannh@google.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: transition from a list of rules to a vector of rules</title>
<updated>2025-07-20T09:31:06+00:00</updated>
<author>
<name>John Johansen</name>
<email>john.johansen@canonical.com</email>
</author>
<published>2025-02-17T09:46:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=9afdc6abb007d5a86f54e9f10870ac1468155ca5'/>
<id>9afdc6abb007d5a86f54e9f10870ac1468155ca5</id>
<content type='text'>
The set of rules on a profile is not dynamically extended, instead
if a new ruleset is needed a new version of the profile is created.
This allows us to use a vector of rules instead of a list, slightly
reducing memory usage and simplifying the code.

Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The set of rules on a profile is not dynamically extended, instead
if a new ruleset is needed a new version of the profile is created.
This allows us to use a vector of rules instead of a list, slightly
reducing memory usage and simplifying the code.

Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: add missing params to aa_may_ptrace kernel-doc comments</title>
<updated>2023-11-19T09:19:41+00:00</updated>
<author>
<name>John Johansen</name>
<email>john.johansen@canonical.com</email>
</author>
<published>2023-11-19T09:19:41+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=a7e405a2de69fe5e6657046e978a81683b140051'/>
<id>a7e405a2de69fe5e6657046e978a81683b140051</id>
<content type='text'>
When the cred was explicit passed through to aa_may_ptrace() the
kernel-doc comment was not properly updated.

Reported-by: kernel test robot &lt;lkp@intel.com&gt;
Closes: https://lore.kernel.org/oe-kbuild-all/202311040508.AUhi04RY-lkp@intel.com/
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When the cred was explicit passed through to aa_may_ptrace() the
kernel-doc comment was not properly updated.

Reported-by: kernel test robot &lt;lkp@intel.com&gt;
Closes: https://lore.kernel.org/oe-kbuild-all/202311040508.AUhi04RY-lkp@intel.com/
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: add user namespace creation mediation</title>
<updated>2023-10-18T22:49:02+00:00</updated>
<author>
<name>John Johansen</name>
<email>john.johansen@canonical.com</email>
</author>
<published>2022-09-09T23:00:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=fa9b63adabcfa9b724120ef3352cf6fb82b4b9a5'/>
<id>fa9b63adabcfa9b724120ef3352cf6fb82b4b9a5</id>
<content type='text'>
Unprivileged user namespace creation is often used as a first step
in privilege escalation attacks. Instead of disabling it at the
sysrq level, which blocks its legitimate use as for setting up a sandbox,
allow control on a per domain basis.

This allows an admin to quickly lock down a system while also still
allowing legitimate use.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Unprivileged user namespace creation is often used as a first step
in privilege escalation attacks. Instead of disabling it at the
sysrq level, which blocks its legitimate use as for setting up a sandbox,
allow control on a per domain basis.

This allows an admin to quickly lock down a system while also still
allowing legitimate use.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: pass cred through to audit info.</title>
<updated>2023-10-18T22:30:38+00:00</updated>
<author>
<name>John Johansen</name>
<email>john.johansen@canonical.com</email>
</author>
<published>2022-09-20T03:48:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=90c436a64a6e20482a9a613c47eb4af2e8a5328e'/>
<id>90c436a64a6e20482a9a613c47eb4af2e8a5328e</id>
<content type='text'>
The cred is needed to properly audit some messages, and will be needed
in the future for uid conditional mediation. So pass it through to
where the apparmor_audit_data struct gets defined.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The cred is needed to properly audit some messages, and will be needed
in the future for uid conditional mediation. So pass it through to
where the apparmor_audit_data struct gets defined.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: rename audit_data-&gt;label to audit_data-&gt;subj_label</title>
<updated>2023-10-18T22:30:34+00:00</updated>
<author>
<name>John Johansen</name>
<email>john.johansen@canonical.com</email>
</author>
<published>2022-09-19T07:46:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=d20f5a1a6e792d22199c9989ec7ab9e95c48d60c'/>
<id>d20f5a1a6e792d22199c9989ec7ab9e95c48d60c</id>
<content type='text'>
rename audit_data's label field to subj_label to better reflect its
use. Also at the same time drop unneeded assignments to -&gt;subj_label
as the later call to aa_check_perms will do the assignment if needed.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
rename audit_data's label field to subj_label to better reflect its
use. Also at the same time drop unneeded assignments to -&gt;subj_label
as the later call to aa_check_perms will do the assignment if needed.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: combine common_audit_data and apparmor_audit_data</title>
<updated>2023-10-18T22:30:29+00:00</updated>
<author>
<name>John Johansen</name>
<email>john.johansen@canonical.com</email>
</author>
<published>2022-09-14T07:20:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=bd7bd201ca46c211c3ab251ca9854787d1331a2f'/>
<id>bd7bd201ca46c211c3ab251ca9854787d1331a2f</id>
<content type='text'>
Everywhere where common_audit_data is used apparmor audit_data is also
used. We can simplify the code and drop the use of the aad macro
everywhere by combining the two structures.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Everywhere where common_audit_data is used apparmor audit_data is also
used. We can simplify the code and drop the use of the aad macro
everywhere by combining the two structures.

Reviewed-by: Georgia Garcia &lt;georgia.garcia@canonical.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: make aa_set_current_onexec return void</title>
<updated>2023-07-10T00:30:51+00:00</updated>
<author>
<name>Quanfa Fu</name>
<email>quanfafu@gmail.com</email>
</author>
<published>2023-01-14T16:49:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=0897fcb1c1e7316375166e0a665237bce2391a09'/>
<id>0897fcb1c1e7316375166e0a665237bce2391a09</id>
<content type='text'>
Change the return type to void since it always return 0, and no need
to do the checking in aa_set_current_onexec.

Signed-off-by: Quanfa Fu &lt;quanfafu@gmail.com&gt;
Reviewed-by: "Tyler Hicks (Microsoft)" &lt;code@tyhicks.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Change the return type to void since it always return 0, and no need
to do the checking in aa_set_current_onexec.

Signed-off-by: Quanfa Fu &lt;quanfafu@gmail.com&gt;
Reviewed-by: "Tyler Hicks (Microsoft)" &lt;code@tyhicks.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: Simplify obtain the newest label on a cred</title>
<updated>2022-10-03T21:49:04+00:00</updated>
<author>
<name>Gaosheng Cui</name>
<email>cuigaosheng1@huawei.com</email>
</author>
<published>2022-09-23T09:21:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=adaa9a3f72e6f98538bfac54f6dc4afc0537f410'/>
<id>adaa9a3f72e6f98538bfac54f6dc4afc0537f410</id>
<content type='text'>
In aa_get_task_label(), aa_get_newest_cred_label(__task_cred(task))
can do the same things as aa_get_newest_label(__aa_task_raw_label(task)),
so we can replace it and remove __aa_task_raw_label() to simplify the code.

Signed-off-by: Gaosheng Cui &lt;cuigaosheng1@huawei.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In aa_get_task_label(), aa_get_newest_cred_label(__task_cred(task))
can do the same things as aa_get_newest_label(__aa_task_raw_label(task)),
so we can replace it and remove __aa_task_raw_label() to simplify the code.

Signed-off-by: Gaosheng Cui &lt;cuigaosheng1@huawei.com&gt;
Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>apparmor: rework profile-&gt;rules to be a list</title>
<updated>2022-10-03T21:49:04+00:00</updated>
<author>
<name>John Johansen</name>
<email>john.johansen@canonical.com</email>
</author>
<published>2022-09-06T03:47:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux-stable.git/commit/?id=1ad22fcc4d0d2fb2e0f35aed555a86d016d5e590'/>
<id>1ad22fcc4d0d2fb2e0f35aed555a86d016d5e590</id>
<content type='text'>
Convert profile-&gt;rules to a list as the next step towards supporting
multiple rulesets in a profile. For this step only support a single
list entry item. The logic for iterating the list will come as a
separate step.

Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Convert profile-&gt;rules to a list as the next step towards supporting
multiple rulesets in a profile. For this step only support a single
list entry item. The logic for iterating the list will come as a
separate step.

Signed-off-by: John Johansen &lt;john.johansen@canonical.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
