data built 2026-10-19T13:16:53Z

Look up another CVE · open CVE-2026-89762 in the interactive tracker

CVE-2026-89762

apparmor: fix cred UAF caused by begin_current_label_crit_section()

7.8 EPSS 0.1% AV:L

Published 2026-09-11 (37 days ago) by the Linux kernel CNA. Subsystem security/apparmor. Debian urgency: not yet assigned.

What to do, per Debian release

Debian's own status for CVE-2026-89762 in every release this site tracks, and what each one means in practice. Every status below is the one the Debian Security Team publishes for this CVE. source

ReleaseStatus VersionWhat this means
Debian 12bookwormvulnerable6.1.190-1No fix published anywhere yet, neither in Debian nor upstream for the series bookworm tracks. Watch the Debian tracker page for this CVE. Advisories for bookworm have historically landed a median of 23 days after publication.
Debian 13trixiefixedDSA-6528-1 · 2026-09-29 · text6.12.111-1Update the kernel and reboot. DSA-6528-1 shipped the fix on 2026-09-29, in 6.12.111-1. A running kernel keeps the old code until the machine restarts.
Debian 14forkyfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.
Debian unstablesidfixed7.2.6-1Update the kernel and reboot. Fixed in 7.2.6-1. A running kernel keeps the old code until the machine restarts.
Debian 12bookworm · linux-6.12fixedDLA-4817-1 · 2026-10-04 · text6.12.111-1~deb12u1Update the kernel and reboot. DLA-4817-1 shipped the fix on 2026-10-04, in 6.12.111-1~deb12u1. A running kernel keeps the old code until the machine restarts.

The vulnerability

What the bug is

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->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 <creds A> (as both objective and subjective creds), with refcount=2 2. task grabs an extra reference on <creds A> for overriding 3. task calls override_creds(<creds A>), which returns a pointer to the old subjective creds (<creds A>) 4. task enters AppArmor LSM hook 5. AppArmor checks that objective/subjective creds are equal 6. AppArmor replaces both cred pointers with <creds B> and drops 2 refs on <creds A> 7. task leaves AppArmor LSM hook 8. task calls revert_creds(<creds A>) 9. now task->cred is <creds A> while task->real_cred is <creds B>, but the task_struct logically holds two references to <creds B> 10. another task drops the extra reference on <creds A> that was used for overriding, refcount drops to 0 11. now task->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 ->write() callbacks via proc_pid_attr_write(). There are two options for what to do with aa_dup_task_ctx(): Either explicitly reset new->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.

Where it lives

The fix touches these files. If the subsystem is one you do not use, the practical exposure is lower, though the package is still the vulnerable one.

security/apparmor/include/cred.h
security/apparmor/include/task.h
security/apparmor/task.c

What this is
APPARMOR SECURITY MODULEMAINTAINERS section matched on security/apparmor/ · apparmor@lists.ubuntu.com · Supported

Check it on the machine

grep -w CONFIG_SECURITY_APPARMOR /boot/config-$(uname -r)

Reads the booted kernel's own configuration, on the machine and nowhere else. =y is built in, =m is a module, and an is not set line means the code is not there.

Show whether Debian builds this, per release

Debian builds this code. Every release below compiles the affected file into the kernels it ships.

  • bookworm, trixie, forky, sid, bookworm · linux-6.12y
y
built into the kernel image on every flavour - only a patch removes it
Build switch
CONFIG_SECURITY_APPARMOR

From the configuration Debian publishes for every kernel flavour it builds. It covers only the architectures Debian ships a linux-config package for, and nothing about a kernel you built yourself. Debian's own status above stays authoritative about the source package.MAINTAINERS kbuild Makefiles Debian linux-config packages

Signals

Published
2026-09-11 (37 days ago)source
CVSS
7.8 high
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:Hsource recompute it
Attack vector
local (AV:L)source
EPSS
0.12%, higher than 1.8% of all CVEssource
CISA KEV
not listedthe KEV catalogue
Debian urgency
not yet assignedsource
Subsystem
security/apparmor

Upstream fixes

The versions the CNA records as introducing and fixing this, and the commit for each. source

IntroducedFixed inCommit
2.6.366.12.109361488984d66
2.6.366.18.50587a6a92b93e
2.6.367.2.4580f777d6d9f
2.6.367.33f4ae5fab613

Debian advisories

AdvisoryDateShipped toDebian
DLA-4817-12026-10-04bookworm 6.12.111-1~deb12u1tracker
DSA-6528-12026-09-29trixie 6.12.111-1tracker

Why the CNA scored it this way

Quoted from the kernel CNA's own scoring file, word for word. A highlighted metric carries the most severe value CVSS v3.1 defines for it, which is what pushes the score up. source

AV:LAttack vector, local
begin_current_label_crit_section() runs from AppArmor LSM hooks on local VFS/socket syscalls after a stale profile replace. The confirmed UAF is splice from a FUSE passthrough file under override_creds() of the same cred object; unprivileged binfmt_misc register does the same around open_exec(). This is not a network receive path.
AC:LAttack complexity, low
The attacker controls both sides: they replace the AppArmor profile to mark the task label FLAG_STALE, then invoke a syscall that override_creds()s with that same cred object (FUSE passthrough splice into a full pipe, or binfmt_misc OPEN_FILE register). The author’s sequence is attacker-driven, not a victim-dependent race.
PR:LPrivileges required, low
Making the label stale requires AppArmor policy replace (CAP_MAC_ADMIN), but unprivileged_userns_apparmor_policy defaults to 1 so userns root can load/replace policy. The LSM hooks and same-cred override_creds sites, including unprivileged binfmt_misc (FS_USERNS_MOUNT), are reachable without init-namespace root.
UI:NUser interaction, none
The attacker confines their own task, replaces their own policy, and triggers the override_creds VFS path themselves; no separate victim user action is required.
S:UScope, unchanged
Impact is a kernel struct cred use-after-free and local privilege escalation within the same kernel security authority. It is not a VM escape, IOMMU bypass, or cross-authority sandbox break.
C:HConfidentiality impact, high
This is a use-after-free of struct cred: aa_replace_current_label() drops the task’s refs during override_creds(), then revert_creds() restores a dangling cred pointer. Reclaiming the cred slab yields an arbitrary kernel read. Kernel UAF scores C:H.
I:HIntegrity impact, high
The same cred UAF is a classic heap-spray primitive on struct cred, enabling arbitrary writes and control-flow hijacking / privilege escalation. Kernel UAF scores I:H.
A:HAvailability impact, high
The author reproduced a KASAN use-after-free of current_cred() on a later getuid() after the FUSE splice sequence; dereferencing the freed cred oopses or panics the kernel.