CVE-2026-46223
📛 CVE Title
cgroup: Defer css percpu_ref kill on rmdir until cgroup is depopulated
Description
In the Linux kernel, the following vulnerability has been resolved: cgroup: Defer css percpu_ref kill on rmdir until cgroup is depopulated A chain of commits going back to v7.0 reworked rmdir to satisfy the controller invariant that a subsystem's ->css_offline() must not run while tasks are still doing kernel-side work in the cgroup. [1] d245698d727a ("cgroup: Defer task cgroup unlink until after the task is done switching out") [2] a72f73c4dd9b ("cgroup: Don't expose dead tasks in cgroup") [3] 1b164b876c36 ("cgroup: Wait for dying tasks to leave on rmdir") [4] 4c56a8ac6869 ("cgroup: Fix cgroup_drain_dying() testing the wrong condition") [5] 13e786b64bd3 ("cgroup: Increment nr_dying_subsys_* from rmdir context") [1] moved task cset unlink from do_exit() to finish_task_switch() so a task's cset link drops only after the task has fully stopped scheduling. That made tasks past exit_signals() linger on cset->tasks until their final context switch, which led to a series of problems as what userspace expected to see after rmdir diverged from what the kernel needs to wait for. [2]-[5] tried to bridge that divergence: [2] filtered the exiting tasks from cgroup.procs; [3] had rmdir(2) sleep in TASK_UNINTERRUPTIBLE for them; [4] fixed the wait's condition; [5] made nr_dying_subsys_* visible synchronously. The cgroup_drain_dying() wait in [3] turned out to be a dead end. When the rmdir caller is also the reaper of a zombie that pins a pidns teardown (e.g. host PID 1 systemd reaping orphan pids that were re-parented to it during the same teardown), rmdir blocks in TASK_UNINTERRUPTIBLE waiting for those pids to free, the pids can't free because PID 1 is the reaper and it's stuck in rmdir, and the system A-A deadlocks. No internal lock ordering breaks this; the wait itself is the bug. The css killing side that drove the original reorder, however, can be made cleanly asynchronous: ->css_offline() is already async, run from css_killed_work_fn() driven by percpu_ref_kill_and_confirm(). The fix is to make that chain start only after all tasks have left the cgroup. rmdir's user-visible side then returns as soon as cgroup.procs and friends are empty, while ->css_offline() still runs only after the cgroup is fully drained. Verified by the original reproducer (pidns teardown + zombie reaper, runs under vng) which hangs vanilla and succeeds here, and by per-commit deterministic repros for [2], [3], [4], [5] with a boot parameter that widens the post-exit_signals() window so each state is reliably reachable. Some stress tests on top of that. cgroup_apply_control_disable() has the same shape of pre-existing race: when a controller is disabled via subtree_control, kill_css() ran synchronously while tasks past exit_signals() could still be linked to the cgroup's csets, and ->css_offline() could fire before they drained. This patch preserves the existing synchronous behavior at that call site (kill_css_sync() + kill_css_finish() back-to-back) and a follow-up patch will defer kill_css_finish() there using a per-css trigger. This seems like the right approach and I don't see problems with it. The changes are somewhat invasive but not excessively so, so backporting to -stable should be okay. If something does turn out to be wrong, the fallback is to revert the entire chain ([1]-[5]) and rework in the development branch instead. v2: Pin cgrp across the deferred destroy work with explicit cgroup_get()/cgroup_put() around queue_work() and the work_fn. v1 wasn't actually broken (ordered cgroup_offline_wq + queue_work order in cgroup_task_dead() saved it) but the explicit ref removes the dependency on those non-obvious invariants. Also note the pre-existing cgroup_apply_control_disable() race in the description; a follow-up will defer kill_css_finish() there.
Overview
- State
- PUBLISHED
- Assigner (CNA)
- Linux
- CVSS severity
- high
- CVSS score
- 8.4 / 10
- CVSS vector
AV:L/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:H- Effective score
- 8.4 / 10 HIGH source: CNA overview
- CWE(s)
- —
- Reserved
- 2026-05-13
- Published
- 2026-05-28 09:40 UTC
- Last updated
- 2026-05-28 09:40 UTC
- Source
- https://raw.githubusercontent.com/CVEProject/cvelistV5/main/cves/2026/46xxx/CVE-2026-46223.json
- Linked Threat
- CVE-2026-46223 — CVE-2026-46223
NVD triage scoring NVD CVE 2.0
Layer NVD adds on top of the CNA's CVE record — published / last-modified timestamps, exploitability / impact subscores, and the FIRST.org EPSS probability that this CVE will be exploited in the wild in the next 30 days.
- NVD published
- 2026-05-28 10:16:37 UTC
- NVD last modified
- 2026-06-17 10:53:21 UTC
- NVD CVSS v3.1
- 5.5 / 10 MEDIUM source: nvd@nist.gov
- NVD CVSS vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H- Exploitability subscore
- 1.8 / 10
- Impact subscore
- 3.6 / 10
- EPSS score
- 0.0008 (probability of exploitation in next 30 days)
- EPSS percentile
- 0.32% vs all CVEs — higher = more likely to be exploited, as of 2026-07-28
NVD-assigned CWE(s):
CWE-667
(differs from the CNA list above)
NVD / KEV / EPSS data refreshed 2026-07-28 15:55 UTC. Re-run the 🛰 Backfill from NVD button above to refresh.
European Union Vulnerability Database ENISA EUVD
ENISA's official EU repository for curated vulnerability intelligence. Carries a separate identifier (EUVD-YYYY-NNNN) and frequently exposes an earlier-published description + CVSS than NVD does.
- EUVD ID
-
EUVD-2026-32850 - Assigner
- Linux
- Published
- May 28, 2026, 9:40:40 AM
- Updated
- Jun 14, 2026, 6:03:52 PM
- EUVD base score
- 0.0 / 10
- EUVD-reported EPSS
- 0.0800
- Vendors
- Linux
- Products
-
Linux (patch: 7.1)Linux (78c72bce4a87819126211c0d24e18350010604fb)Linux (1b164b876c36c3eb5561dd9b37702b04401b0166 <33fa2e6b1507a0a377a151a8826438bedad1d0b0)Linux (patch: 7.0.9)Linux (6.19.12 <6.20)Linux (7.0)Linux (1b164b876c36c3eb5561dd9b37702b04401b0166 <93618edf753838a727dbff63c7c291dee22d656b)Linux (patch: 0)
- Aliases
-
GHSA-r8hv-j9g9-64g6
ENISA description: In the Linux kernel, the following vulnerability has been resolved: cgroup: Defer css percpu_ref kill on rmdir until cgroup is depopulated A chain of commits going back to v7.0 reworked rmdir to satisfy the controller invariant that a subsystem's ->css_offline() must not run while tasks are still doing kernel-side work in the cgroup. [1] d245698d727a ("cgroup: Defer task cgroup unlink until after the task is done switching out") [2] a72f73c4dd9b ("cgroup: Don't expose dead tasks in cgroup") [3] 1b164b876c36 ("cgroup: Wait for dying tasks to leave on rmdir") [4] 4c56a8ac6869 ("cgroup: Fix cgroup_drain_dying() testing the wrong condition") [5] 13e786b64bd3 ("cgroup: Increment nr_dying_subsys_* from rmdir context") [1] moved task cset unlink from do_exit() to finish_task_switch() so a task's cset link drops only after the task has fully stopped scheduling. That made tasks past exit_signals() linger on cset->tasks until their final context switch, which led to a series of problems as what userspace expected to see after rmdir diverged from what the kernel needs to wait for. [2]-[5] tried to bridge that divergence: [2] filtered the exiting tasks from cgroup.procs; [3] had rmdir(2) sleep in TASK_UNINTERRUPTIBLE for them; [4] fixed the wait's condition; [5] made nr_dying_subsys_* visible synchronously. The cgroup_drain_dying() wait in [3] turned out to be a dead end. When the rmdir caller is also the reaper of a zombie that pins a pidns teardown (e.g. host PID 1 systemd reaping orphan pids that were re-parented to it during the same teardown), rmdir blocks in TASK_UNINTERRUPTIBLE waiting for those pids to free, the pids can't free because PID 1 is the reaper and it's stuck in rmdir, and the system A-A deadlocks. No internal lock ordering breaks this; the wait itself is the bug. The css killing side that drove the original reorder, however, can be made cleanly asynchronous: ->css_offline() is already async, run from css_killed_work_fn() driven by percpu_ref_kill_and_confirm(). The fix is to make that chain start only after all tasks have left the cgroup. rmdir's user-visible side then returns as soon as cgroup.procs and friends are empty, while ->css_offline() still runs only after the cgroup is fully drained. Verified by the original reproducer (pidns teardown + zombie reaper, runs under vng) which hangs vanilla and succeeds here, and by per-commit deterministic repros for [2], [3], [4], [5] with a boot parameter that widens the post-exit_signals() window so each state is reliably reachable. Some stress tests on top of that. cgroup_apply_control_disable() has the same shape of pre-existing race: when a controller is disabled via subtree_control, kill_css() ran synchronously while tasks past exit_signals() could still be linked to the cgroup's csets, and ->css_offline() could fire before they drained. This patch preserves the existing synchronous behavior at that call site (kill_css_sync() + kill_css_finish() back-to-back) and a follow-up patch will defer kill_css_finish() there using a per-css trigger. This seems like the right approach and I don't see problems with it. The changes are somewhat invasive but not excessively so, so backporting to -stable should be okay. If something does turn out to be wrong, the fallback is to revert the entire chain ([1]-[5]) and rework in the development branch instead. v2: Pin cgrp across the deferred destroy work with explicit cgroup_get()/cgroup_put() around queue_work() and the work_fn. v1 wasn't actually broken (ordered cgroup_offline_wq + queue_work order in cgroup_task_dead() saved it) but the explicit ref removes the dependency on those non-obvious invariants. Also note the pre-existing cgroup_apply_control_disable() race in the description; a follow-up will defer kill_css_finish() there.
Affected products (2)
| Vendor | Product | Versions | Platforms |
|---|---|---|---|
| Linux | Linux |
1b164b876c36c3eb5561dd9b37702b04401b0166 (affected),
1b164b876c36c3eb5561dd9b37702b04401b0166 (affected),
78c72bce4a87819126211c0d24e18350010604fb (affected),
6.19.12 (affected)
|
— |
| Linux | Linux |
7.0 (affected),
0 (unaffected),
7.0.9 (unaffected),
7.1-rc3 (unaffected)
|
— |
Affected products — CPE 2.3 (5) NVD
NVD's normalized CPE 2.3 matchers, used by vendor tools (vulnerability scanners, asset managers) for automated detection. Compare with the CNA's free-text "Affected products" section above.
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*cpe:2.3:o:linux:linux_kernel:7.0:-:*:*:*:*:*:*cpe:2.3:o:linux:linux_kernel:7.0:rc7:*:*:*:*:*:*cpe:2.3:o:linux:linux_kernel:7.1:rc1:*:*:*:*:*:*cpe:2.3:o:linux:linux_kernel:7.1:rc2:*:*:*:*:*:*
Vendor references (2)
References embedded in the original CVE record by the assigning CNA.
Web references (5)
DuckDuckGo results ranked by threat-intel / vendor advisory domains. Generated by the 🔎 Find references (web) button above — same flow as the Remediations search.
- https://git.kernel.org/stable/c/33fa2e6b1507a0a377a151a8826438bedad1d0b0 tenable:git.kernel.org
- https://git.kernel.org/stable/c/93618edf753838a727dbff63c7c291dee22d656b tenable:git.kernel.org
- https://nvd.nist.gov/vuln/detail/CVE-2026-46223 tenable:nvd.nist.gov
- https://www.cve.org/CVERecord?id=CVE-2026-46223 tenable:www.cve.org
- https://www.first.org/epss/ tenable:www.first.org
NVD-tagged references (2)
Reference list NVD curates from the CNA record, vendor advisories, and third-party reports. The tag chips below are NVD's analyst-assigned categories.
- https://git.kernel.org/stable/c/33fa2e6b1507a0a377a151a8826438bedad1d0b0 416baaa9-dc9f-4396-8d5f-8c081fb06d67 Patch
- https://git.kernel.org/stable/c/93618edf753838a727dbff63c7c291dee22d656b 416baaa9-dc9f-4396-8d5f-8c081fb06d67 Patch
Remediations (17)
Remediations are stored against the linked Threat row; the list below is deduplicated across both pages.
-
web:access.redhat.com
Applying the kernel fix , when available, is the only comprehensive remediation . Option 1: Admin-only scope Setting ptrace_scope to 2 restricts ptrace attach to processes with CAP_SYS_PTRACE. This blocks many currently known exploitation paths, but other paths that do not rely on ptrace may exist. This is suitable for most production environments.
2026-06-03 23:59 UTC -
web:blog.cloudlinux.com
CIFSwitch is a Linux kernel privilege escalation affecting CloudLinux 7h/8/9/10 hosts that have cifs-utils installed. Mitigation and patched kernels are available.
2026-06-03 23:59 UTC -
web:cybersecuritynews.com
Microsoft has released its April 2026 Patch Tuesday security update, addressing 168 vulnerabilities across its product portfolio including one actively exploited zero-day and one publicly disclosed flaw that organizations must prioritize immediately.
2026-06-03 23:59 UTC -
web:integsec.com
CVE - 2026 -46333 matters because it transforms any local user account on your Linux servers into a potential root-level compromise. This vulnerability affects organizations across North America that rely on Linux infrastructure for everything from web hosting to database management and cloud services. If your business operates servers running unpatched Linux kernels, you face genuine risk of ...
2026-06-03 23:59 UTC -
web:portal.msrc.microsoft.com
The Security Update Guide provides information on the latest Microsoft security updates, helping users understand and address potential vulnerabilities effectively.
2026-06-03 23:59 UTC -
web:www.crowdstrike.com
Microsoft's April 2026 Patch Tuesday addresses 164 CVEs , featuring 8 Critical vulnerabilities, one exploited zero-day, and one disclosed zero-day.
2026-06-03 23:59 UTC -
web:www.oracle.com
This Critical Patch Update contains 481 new security patches across the product families listed below. Please note that an MOS note summarizing the content of this Critical Patch Update and other Oracle Software Security Assurance activities is located at April 2026 Critical Patch Update: Executive Summary and Analysis.
2026-06-03 23:59 UTC -
web:www.secure.com
Remediation fully removes a vulnerability by fixing its root cause — through a patch , code fix , or system replacement. Mitigation reduces the risk of exploitation without removing the flaw itself, using controls like network segmentation or access restrictions.
2026-06-03 23:59 UTC -
web:www.securityweek.com
Oracle on Tuesday announced the release of 481 new security patches as part of its April 2026 Critical Patch Update (CPU). Across the 28 product families that received security updates, more than 300 patches address vulnerabilities that are remotely exploitable without authentication.
2026-06-03 23:59 UTC -
web:zecurit.com
Get the complete breakdown of Microsoft's June 2026 Patch Tuesday. We analyze the latest security updates and all critical CVEs .
2026-06-03 23:59 UTC -
web:blog.qualys.com
May 2026's Patch Tuesday arrives with Microsoft addressing a fresh set of vulnerabilities across its ecosystem, reinforcing the ongoing need for timely patching in an increasingly threat-heavy…
2026-06-19 02:28 UTC -
web:cybersecuritynews.com
Microsoft's May 2026 Patch Tuesday lands with a heavy enterprise focus, fixing 120 vulnerabilities across Windows, Office, Azure, developer tools, and Microsoft 365 apps, including 29 remote code execution (RCE) flaws rated Critical.
2026-06-19 02:28 UTC -
web:www.crowdstrike.com
Microsoft's March 2026 Patch Tuesday addresses 82 CVEs , featuring eight Critical vulnerabilities.
2026-06-19 02:28 UTC -
web:www.microsoft.com
Security Update Guide Notifications Microsoft's free Security Update Guide Notifications provide links to security-related software updates and notification of re-released security updates. These notifications are sent via email throughout the month as needed.
2026-06-19 02:28 UTC -
web:www.oracle.com
This Critical Security Patch Update contains 35 new security patches across the product families listed below. Please note that an MOS note summarizing the content of this Critical Security Patch Update and other Oracle Software Security Assurance activities is located at May 2026 Critical Security Patch Update: Executive Summary and Analysis.
2026-06-19 02:28 UTC -
web:www.rapid7.com
Microsoft is publishing 200 vulnerabilities on June 2026 Patch Tuesday, including an HTTP/2 denial of service vulnerability and an elevation of privilege vulnerability in PowerToys.
2026-06-19 02:28 UTC -
web:www.veeam.com
When a vulnerability is identified, our team promptly develops a patch to address and mitigate the risk. In line with our dedication to transparency, we publicly disclose the vulnerability and provide detailed mitigation information.
2026-06-19 02:28 UTC
AI Forensic Analysis
Only Available for Registered Users. Sign in to view.
Raw JSON
The full cvelistV5 record. Download as CVE-2026-46223.json.
{
"containers": {
"cna": {
"affected": [
{
"defaultStatus": "unaffected",
"product": "Linux",
"programFiles": [
"include/linux/cgroup-defs.h",
"kernel/cgroup/cgroup.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"lessThan": "33fa2e6b1507a0a377a151a8826438bedad1d0b0",
"status": "affected",
"version": "1b164b876c36c3eb5561dd9b37702b04401b0166",
"versionType": "git"
},
{
"lessThan": "93618edf753838a727dbff63c7c291dee22d656b",
"status": "affected",
"version": "1b164b876c36c3eb5561dd9b37702b04401b0166",
"versionType": "git"
},
{
"status": "affected",
"version": "78c72bce4a87819126211c0d24e18350010604fb",
"versionType": "git"
},
{
"lessThan": "6.20",
"status": "affected",
"version": "6.19.12",
"versionType": "semver"
}
]
},
{
"defaultStatus": "affected",
"product": "Linux",
"programFiles": [
"include/linux/cgroup-defs.h",
"kernel/cgroup/cgroup.c"
],
"repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
"vendor": "Linux",
"versions": [
{
"status": "affected",
"version": "7.0"
},
{
"lessThan": "7.0",
"status": "unaffected",
"version": "0",
"versionType": "semver"
},
{
"lessThanOrEqual": "7.0.*",
"status": "unaffected",
"version": "7.0.9",
"versionType": "semver"
},
{
"lessThanOrEqual": "*",
"status": "unaffected",
"version": "7.1-rc3",
"versionType": "original_commit_for_fix"
}
]
}
],
"cpeApplicability": [
{
"nodes": [
{
"cpeMatch": [
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "7.0.9",
"versionStartIncluding": "7.0",
"vulnerable": true
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionEndExcluding": "7.1-rc3",
"versionStartIncluding": "7.0",
"vulnerable": true
},
{
"criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
"versionStartIncluding": "6.19.12",
"vulnerable": true
}
],
"negate": false,
"operator": "OR"
}
]
}
],
"descriptions": [
{
"lang": "en",
"value": "In the Linux kernel, the following vulnerability has been resolved:\n\ncgroup: Defer css percpu_ref kill on rmdir until cgroup is depopulated\n\nA chain of commits going back to v7.0 reworked rmdir to satisfy the\ncontroller invariant that a subsystem's ->css_offline() must not run while\ntasks are still doing kernel-side work in the cgroup.\n\n[1] d245698d727a (\"cgroup: Defer task cgroup unlink until after the task is done switching out\")\n[2] a72f73c4dd9b (\"cgroup: Don't expose dead tasks in cgroup\")\n[3] 1b164b876c36 (\"cgroup: Wait for dying tasks to leave on rmdir\")\n[4] 4c56a8ac6869 (\"cgroup: Fix cgroup_drain_dying() testing the wrong condition\")\n[5] 13e786b64bd3 (\"cgroup: Increment nr_dying_subsys_* from rmdir context\")\n\n[1] moved task cset unlink from do_exit() to finish_task_switch() so a\ntask's cset link drops only after the task has fully stopped scheduling.\nThat made tasks past exit_signals() linger on cset->tasks until their final\ncontext switch, which led to a series of problems as what userspace expected\nto see after rmdir diverged from what the kernel needs to wait for. [2]-[5]\ntried to bridge that divergence: [2] filtered the exiting tasks from\ncgroup.procs; [3] had rmdir(2) sleep in TASK_UNINTERRUPTIBLE for them; [4]\nfixed the wait's condition; [5] made nr_dying_subsys_* visible\nsynchronously.\n\nThe cgroup_drain_dying() wait in [3] turned out to be a dead end. When the\nrmdir caller is also the reaper of a zombie that pins a pidns teardown (e.g.\nhost PID 1 systemd reaping orphan pids that were re-parented to it during\nthe same teardown), rmdir blocks in TASK_UNINTERRUPTIBLE waiting for those\npids to free, the pids can't free because PID 1 is the reaper and it's stuck\nin rmdir, and the system A-A deadlocks. No internal lock ordering breaks\nthis; the wait itself is the bug.\n\nThe css killing side that drove the original reorder, however, can be made\ncleanly asynchronous: ->css_offline() is already async, run from\ncss_killed_work_fn() driven by percpu_ref_kill_and_confirm(). The fix is to\nmake that chain start only after all tasks have left the cgroup. rmdir's\nuser-visible side then returns as soon as cgroup.procs and friends are\nempty, while ->css_offline() still runs only after the cgroup is fully\ndrained.\n\nVerified by the original reproducer (pidns teardown + zombie reaper, runs\nunder vng) which hangs vanilla and succeeds here, and by per-commit\ndeterministic repros for [2], [3], [4], [5] with a boot parameter that\nwidens the post-exit_signals() window so each state is reliably reachable.\nSome stress tests on top of that.\n\ncgroup_apply_control_disable() has the same shape of pre-existing race:\nwhen a controller is disabled via subtree_control, kill_css() ran\nsynchronously while tasks past exit_signals() could still be linked to\nthe cgroup's csets, and ->css_offline() could fire before they drained.\nThis patch preserves the existing synchronous behavior at that call site\n(kill_css_sync() + kill_css_finish() back-to-back) and a follow-up patch\nwill defer kill_css_finish() there using a per-css trigger.\n\nThis seems like the right approach and I don't see problems with it. The\nchanges are somewhat invasive but not excessively so, so backporting to\n-stable should be okay. If something does turn out to be wrong, the fallback\nis to revert the entire chain ([1]-[5]) and rework in the development branch\ninstead.\n\nv2: Pin cgrp across the deferred destroy work with explicit\n cgroup_get()/cgroup_put() around queue_work() and the work_fn. v1\n wasn't actually broken (ordered cgroup_offline_wq + queue_work order\n in cgroup_task_dead() saved it) but the explicit ref removes the\n dependency on those non-obvious invariants. Also note the\n pre-existing cgroup_apply_control_disable() race in the description;\n a follow-up will defer kill_css_finish() there."
}
],
"providerMetadata": {
"dateUpdated": "2026-05-28T09:40:40.791Z",
"orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"shortName": "Linux"
},
"references": [
{
"url": "https://git.kernel.org/stable/c/33fa2e6b1507a0a377a151a8826438bedad1d0b0"
},
{
"url": "https://git.kernel.org/stable/c/93618edf753838a727dbff63c7c291dee22d656b"
}
],
"title": "cgroup: Defer css percpu_ref kill on rmdir until cgroup is depopulated",
"x_generator": {
"engine": "bippy-1.2.0"
}
}
},
"cveMetadata": {
"assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
"assignerShortName": "Linux",
"cveId": "CVE-2026-46223",
"datePublished": "2026-05-28T09:40:40.791Z",
"dateReserved": "2026-05-13T15:03:33.106Z",
"dateUpdated": "2026-05-28T09:40:40.791Z",
"state": "PUBLISHED"
},
"dataType": "CVE_RECORD",
"dataVersion": "5.2"
}