Skip to main content

Linux Kernel CVE-2026-46223

| EUVDEUVD-2026-32850 MEDIUM
Improper Locking (CWE-667)
2026-05-28 416baaa9-dc9f-4396-8d5f-8c081fb06d67 GHSA-r8hv-j9g9-64g6
5.5
CVSS 3.1 · NVD
Share

Severity by source

NVD PRIMARY
5.5 MEDIUM
AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
vuln.today AI
4.7 MEDIUM

AC:H chosen over NVD's AC:L because triggering requires the rare coincidence of the rmdir caller being the active zombie reaper during concurrent pidns teardown; no confidentiality or integrity impact applies.

3.1 AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H
4.0 AV:L/AC:H/AT:P/PR:L/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
SUSE
4.7 MEDIUM
AV:L/AC:H/PR:L/UI:N/S:U/C:N/I:N/A:H

Primary rating from NVD.

CVSS VectorNVD

CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
Attack Vector
Local
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

5
Analysis Generated
Jun 11, 2026 - 18:38 vuln.today
CVSS changed
Jun 11, 2026 - 18:37 NVD
5.5 (MEDIUM)
Patch available
May 28, 2026 - 12:01 EUVD
CVE Published
May 28, 2026 - 10:16 nvd
MEDIUM 5.5
CVE Published
May 28, 2026 - 10:16 nvd
UNKNOWN (no severity yet)

DescriptionNVD

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.

AnalysisAI

An A-A (same-task) deadlock in the Linux kernel cgroup rmdir path (versions 7.0 through 7.1-rc2 and 6.19.x) can permanently hang the entire system, requiring a hard reboot. When a process acting as both a PID namespace zombie reaper (e.g., systemd/PID 1) and the cgroup rmdir(2) caller encounters dying tasks still linked to cgroup csets, the kernel blocks the reaper indefinitely in TASK_UNINTERRUPTIBLE, creating a circular dependency from which the system cannot recover. No public exploit has been identified at time of analysis, EPSS exploitation probability is extremely low (0.02%), and no CISA KEV listing exists - consistent with the scenario's narrow, operationally specific triggering conditions.

Technical ContextAI

The Linux kernel cgroup v2 subsystem (CPE: cpe:2.3:o:linux:linux_kernel:7.0:-:*:*:*:*:*:*) manages resource control groups via cgroup subsystem states (CSS). The root cause (CWE-667: Improper Locking) is a synchronization dependency introduced by commit 1b164b876c36 ('cgroup: Wait for dying tasks to leave on rmdir'), which inserted a TASK_UNINTERRUPTIBLE wait in the rmdir(2) path via cgroup_drain_dying(). That wait was meant to ensure ->css_offline() (triggered by percpu_ref_kill_and_confirm() on the CSS's percpu_ref) did not fire while tasks were still doing kernel-side work inside the cgroup - a controller invariant established by commit d245698d727a, which moved task cset unlink from do_exit() to finish_task_switch(), creating a post-exit_signals() window where dying tasks remain on cset->tasks. The flaw: the process calling rmdir may itself be the designated reaper for zombies pinning a PID namespace teardown. Those zombies cannot complete their final context switch (and vacate the cset) because their reaper is blocked in the cgroup_drain_dying() wait - producing an A-A deadlock. The fix defers the percpu_ref kill chain launch until after the cgroup is fully drained, making ->css_offline() asynchronous via css_killed_work_fn() and eliminating the blocking dependency from rmdir's hot path.

RemediationAI

Upgrade to Linux kernel 7.0.9 or 7.1-rc3 (or any later stable release), which contain the fix deferring CSS percpu_ref kill until after cgroup depopulation. For the 6.x branch, upgrade to 6.20 or beyond. The upstream fix commits are 33fa2e6b1507a0a377a151a8826438bedad1d0b0 and 93618edf753838a727dbff63c7c291dee22d656b, accessible at https://git.kernel.org/stable/c/33fa2e6b1507a0a377a151a8826438bedad1d0b0 and https://git.kernel.org/stable/c/93618edf753838a727dbff63c7c291dee22d656b. For systems that cannot be patched immediately, the most effective compensating control is to ensure container runtimes (Docker, containerd, systemd-nspawn) fully complete PID namespace teardown and zombie reaping before issuing cgroup rmdir operations - most modern runtimes already attempt this ordering, but verifying runtime configuration and sequencing in orchestration teardown logic (e.g., Kubernetes pod termination hooks) can reduce exposure. There is no kernel configuration toggle to disable the affected code path; patching is the only definitive fix. Trade-off of the workaround: it requires operational discipline at the container lifecycle layer and cannot fully eliminate the race on systems with complex PID namespace inheritance patterns.

Vendor StatusVendor

SUSE

Severity: Moderate
Product Status
openSUSE Tumbleweed Fixed
SUSE Linux Enterprise Desktop 15 SP7 Not-Affected
SUSE Linux Enterprise Desktop 15 SP7 Not-Affected
SUSE Linux Enterprise High Availability Extension 15 SP7 Not-Affected
SUSE Linux Enterprise High Availability Extension 15 SP7 Not-Affected

Share

CVE-2026-46223 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy