Files
vuln-cve/data/2026/89xxx/CVE-2026-89762.json
T

226 lines
15 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{
"dataType": "CVE_RECORD",
"dataVersion": "5.2",
"cveMetadata": {
"cveId": "CVE-2026-89762",
"assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"state": "PUBLISHED",
"assignerShortName": "Linux",
"dateReserved": "2026-09-11T19:38:34.764Z",
"datePublished": "2026-09-11T19:47:03.601Z",
"dateUpdated": "2026-10-30T12:32:59.196Z"
},
"containers": {
"cna": {
"providerMetadata": {
"orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"shortName": "Linux",
"dateUpdated": "2026-10-30T12:32:59.196Z"
},
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\napparmor: fix cred UAF caused by begin_current_label_crit_section()\n\nAppArmor's begin_current_label_crit_section() is a scary function called\nfrom lots of LSM hooks (in particular VFS/socket-related ones) that checks\nif the label referenced by the current creds is marked FLAG_STALE, and if\nso, attempts to use aa_replace_current_label() to replace the creds with an\nupdated version that uses a new label.\n\nThe first problem with this is that it would directly lead to UAF of\n`struct cred` if anything in the kernel takes a pointer to the current\ncreds and accesses these past a security hook invocation that replaces\ncreds, like so:\n```\nconst struct cred *cred = current_cred();\nalloc_file_pseudo(...);\nuid_t uid = cred->euid;\n```\nI don't know if anything in the kernel actually does this, but I think it\nis very surprising that this pattern could lead to UAF.\n\nThe second problem is that things go wrong when aa_replace_current_label()\nruns with overridden credentials. aa_replace_current_label() bails out if\n`current_cred() != current_real_cred()` (mirroring the check in\nproc_pid_attr_write()), but this check can't actually reliably detect\noverridden credentials because the overridden creds can be the same as the\nobjective creds.\n\nSo in approximately the following scenario, things go wrong:\n\n1. task begins with <creds A> (as both objective and subjective creds),\n with refcount=2\n2. task grabs an extra reference on <creds A> for overriding\n3. task calls override_creds(<creds A>), which returns a pointer to the old\n subjective creds (<creds A>)\n4. task enters AppArmor LSM hook\n5. AppArmor checks that objective/subjective creds are equal\n6. AppArmor replaces both cred pointers with <creds B> and drops 2 refs on\n <creds A>\n7. task leaves AppArmor LSM hook\n8. task calls revert_creds(<creds A>)\n9. now task->cred is <creds A> while task->real_cred is <creds B>, but the\n task_struct logically holds two references to <creds B>\n10. another task drops the extra reference on <creds A> that was used for\n overriding, refcount drops to 0\n11. now task->real_cred points to freed creds\n\nAt this point, any access to current_cred() will be UAF.\n\nI have a test case where I run aa-disable on a profile while a process\nusing that profile is blocked on splice() from a FUSE passthrough file into\na full pipe; after the profile update, the pipe becomes empty, splice()\nresumes, the credentials go out of sync, and a subsequent getuid() syscall\nresults in a KASAN UAF splat.\n\nTo fix this, instead of directly replacing creds, do it via task_work that\nwill run at the end of the current syscall. (The point in time at which the\ncred replacement happens should have no correctness impact; it is just a\nperformance optimization to avoid unnecessarily touching the refcount of\nthe new label.)\n\nNote that AppArmor still performs direct cred replacements in the\nsb_pivotroot LSM hook after this change, and that direct cred replacements\ncan still happen in VFS ->write() callbacks via proc_pid_attr_write().\n\nThere are two options for what to do with aa_dup_task_ctx(): Either\nexplicitly reset new->label_replacement_pending after the entire\naa_task_ctx has been copied, or switch to manually copying members over.\nI am switching to manually copying members over because that should make\nbugs more obvious."
}
],
"metrics": [
{
"cvssV3_1": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
"baseScore": 7.8,
"baseSeverity": "HIGH"
},
"scenarios": [
{
"lang": "en",
"value": "AV:L - 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.\nAC:L - 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.\nPR:L - 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.\nUI:N - 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.\nS:U - 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.\nC:H - 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.\nI:H - 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.\nA:H - 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."
}
]
}
],
"affected": [
{
"product": "Linux",
"vendor": "Linux",
"defaultStatus": "unaffected",
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"programFiles": [
"security/apparmor/include/cred.h",
"security/apparmor/include/task.h",
"security/apparmor/task.c"
],
"versions": [
{
"version": "c75afcd153f6147d3b094f45a1d87e5df7f4f053",
"lessThan": "42d0791f8aa90382c22dbe0443712c78d1e9d212",
"status": "affected",
"versionType": "git"
},
{
"version": "c75afcd153f6147d3b094f45a1d87e5df7f4f053",
"lessThan": "089f10b47843a86fa03a8c20799c9353660e5288",
"status": "affected",
"versionType": "git"
},
{
"version": "c75afcd153f6147d3b094f45a1d87e5df7f4f053",
"lessThan": "361488984d668235438faac28635f3632351407f",
"status": "affected",
"versionType": "git"
},
{
"version": "c75afcd153f6147d3b094f45a1d87e5df7f4f053",
"lessThan": "587a6a92b93ec314c583bbf747413af170d42540",
"status": "affected",
"versionType": "git"
},
{
"version": "c75afcd153f6147d3b094f45a1d87e5df7f4f053",
"lessThan": "580f777d6d9fd07fc034bd1aeba5c30fd48871a2",
"status": "affected",
"versionType": "git"
},
{
"version": "c75afcd153f6147d3b094f45a1d87e5df7f4f053",
"lessThan": "3f4ae5fab613dca01d6a2a8210dd832e009fcf47",
"status": "affected",
"versionType": "git"
}
]
},
{
"product": "Linux",
"vendor": "Linux",
"defaultStatus": "affected",
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"programFiles": [
"security/apparmor/include/cred.h",
"security/apparmor/include/task.h",
"security/apparmor/task.c"
],
"versions": [
{
"version": "2.6.36",
"status": "affected"
},
{
"version": "0",
"lessThan": "2.6.36",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.1.191",
"lessThanOrEqual": "6.1.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.6.160",
"lessThanOrEqual": "6.6.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.12.109",
"lessThanOrEqual": "6.12.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "6.18.50",
"lessThanOrEqual": "6.18.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "7.2.4",
"lessThanOrEqual": "7.2.*",
"status": "unaffected",
"versionType": "semver"
},
{
"version": "7.3",
"lessThanOrEqual": "*",
"status": "unaffected",
"versionType": "original_commit_for_fix"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"operator": "OR",
"negate": false,
"cpeMatch": [
{
"vulnerable": true,
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionStartIncluding": "2.6.36",
"versionEndExcluding": "6.1.191"
},
{
"vulnerable": true,
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionStartIncluding": "2.6.36",
"versionEndExcluding": "6.6.160"
},
{
"vulnerable": true,
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionStartIncluding": "2.6.36",
"versionEndExcluding": "6.12.109"
},
{
"vulnerable": true,
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionStartIncluding": "2.6.36",
"versionEndExcluding": "6.18.50"
},
{
"vulnerable": true,
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionStartIncluding": "2.6.36",
"versionEndExcluding": "7.2.4"
},
{
"vulnerable": true,
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionStartIncluding": "2.6.36",
"versionEndExcluding": "7.3"
}
]
}
]
}
],
"references": [
{
"url": "https://git.kernel.org/stable/c/42d0791f8aa90382c22dbe0443712c78d1e9d212"
},
{
"url": "https://git.kernel.org/stable/c/089f10b47843a86fa03a8c20799c9353660e5288"
},
{
"url": "https://git.kernel.org/stable/c/361488984d668235438faac28635f3632351407f"
},
{
"url": "https://git.kernel.org/stable/c/587a6a92b93ec314c583bbf747413af170d42540"
},
{
"url": "https://git.kernel.org/stable/c/580f777d6d9fd07fc034bd1aeba5c30fd48871a2"
},
{
"url": "https://git.kernel.org/stable/c/3f4ae5fab613dca01d6a2a8210dd832e009fcf47"
}
],
"title": "apparmor: fix cred UAF caused by begin_current_label_crit_section()",
"x_generator": {
"engine": "bippy-1.2.0"
}
}
}
}