Cloudanix VulnDB

CVE-2026-46223

Medium · 5.5

CVSS

5.5

EPSS

0.1%

Published

May 28, 2026

CISA due date

—

Cloudanix analysis

Next patch cycle SSVC: Track

A flaw in Linux can let someone with local access make a system or container host freeze by triggering a process cleanup deadlock.

Exploitation
Local Privilege
Attacker needs
Low Privilege
Complexity
Moderate
Impact
Denial Of Service
Component
OS kernel
Class
Race Condition
Remediation
Patch
Effort
Medium
Patch risk
Medium

What it actually does

This is a local Linux kernel availability flaw in cgroup removal and task teardown handling. A privileged or otherwise locally authorized process that can create and remove cgroups, interact with PID namespaces, and cause specific process-exit/reparenting behavior can trigger a kernel-level deadlock. The vulnerable path causes rmdir on a cgroup to wait uninterruptibly for dying tasks to fully leave the cgroup, while the task responsible for reaping those dying processes can itself become stuck in that same rmdir path. The result is an A-A deadlock affecting process management and potentially the whole host. The impact is availability only: no direct confidentiality or integrity impact is described.

Why it matters to the business

Successful exploitation can make a Linux system or container host hang or become partially unusable, disrupting workloads, orchestration, container lifecycle operations, and administrative access. The risk is most relevant on systems where untrusted or semi-trusted local users, containers, build jobs, CI runners, or sandboxed workloads can exercise cgroup and namespace behavior. The CVSS score is moderate, EPSS is currently very low, it is not listed in CISA KEV, and no mature public exploit is indicated, so this should generally be handled through normal kernel patch management unless the affected systems run multi-tenant or untrusted local workloads.

How an attack unfolds

An attacker first needs local code execution with enough permissions to create or manipulate cgroups and process namespaces, either directly on a host or through a container/runtime configuration that exposes those primitives. The attacker then creates a process hierarchy involving a PID namespace and processes that exit in a timing-sensitive way, causing zombie or dying tasks to remain associated with a cgroup while teardown is occurring. The attacker triggers removal of the cgroup, typically through an rmdir-style operation. On vulnerable kernels, the rmdir path waits in an uninterruptible state for dying tasks to fully drain. If the same caller is also responsible for reaping the zombie tasks that must complete before the wait can finish, the system enters a circular wait. This can leave PID 1, a container manager, systemd, or another critical process stuck, leading to a host or workload denial of service.

How to fix it

Upgrade to a Linux kernel version that includes the upstream cgroup fix which defers css percpu_ref kill until the cgroup is depopulated. No exact fixed package versions were provided in the input, so remediation should be tracked through the relevant Linux distribution, kernel vendor, cloud image, appliance, or container-host kernel advisory for CVE-2026-46223. Where immediate patching is not possible, reduce exposure by limiting untrusted local access, restricting container privileges, avoiding delegation of cgroup management to untrusted users, disabling or tightening unprivileged user namespace usage where operationally feasible, and ensuring container runtimes do not grant unnecessary cgroup or namespace capabilities. Because this is a kernel flaw, application-level patching is not sufficient; the running kernel must be updated and the host rebooted or otherwise live-patched if the vendor supports live patching for this issue.

How to confirm the fix worked

Confirm the running kernel package or live-patch level contains the vendor fix for this cgroup deadlock. Validate with the distribution advisory rather than relying only on the upstream commit text, because backported kernel fixes may not change the visible kernel version in an obvious way. Check `uname -a`, kernel package metadata, and vendor security advisory status across all affected Linux hosts and container nodes. After remediation, reboot into the fixed kernel or verify that the live patch is active. Functional validation can include exercising cgroup creation/removal and container/PID namespace teardown workflows in a non-production test environment and confirming they complete without uninterruptible hangs. Also confirm no long-lived processes remain stuck in D state in cgroup removal, PID namespace teardown, or zombie reaping paths.

Typical attack path

  1. Gain local execution on an affected Linux system or in a container/runtime context with access to relevant cgroup and namespace operations.
  2. Create or enter a PID namespace and launch child processes arranged so that some become dying or zombie tasks during namespace teardown.
  3. Ensure the task responsible for reaping those processes is also involved in cgroup removal or teardown.
  4. Remove the affected cgroup using rmdir or an equivalent cgroup cleanup operation while dying tasks are still linked internally.
  5. Trigger the vulnerable kernel wait path, causing the reaper and cgroup removal path to deadlock.
  6. Sustain a denial-of-service condition where process teardown, cgroup cleanup, container lifecycle management, or the host itself becomes stuck.

How to detect it

Detection should focus on evidence of attempted or successful local denial of service rather than network indicators. Review kernel logs, system journals, audit logs, container runtime logs, and orchestration events for repeated cgroup creation/removal, PID namespace teardown failures, blocked tasks, hung task warnings, zombie process buildup, or critical processes stuck in uninterruptible sleep. Useful sources include `journalctl -k`, `/var/log/kern.log`, `/var/log/messages`, auditd syscall records for `rmdir` against cgroup filesystem paths, container runtime logs for container stop/remove hangs, Kubernetes node events for pod termination timeouts, and SysRq blocked-task dumps if collected. In a suspected case, look for stack traces involving cgroup removal or draining functions together with PID namespace teardown or zombie reaping, especially where PID 1, systemd, containerd, runc, crio, kubelet, or a workload reaper is blocked. Absence of these artifacts does not prove absence of exploitation, because a deadlock may require live kernel diagnostics before reboot.

  • INFO: task
  • blocked for more than
  • TASK_UNINTERRUPTIBLE
  • cgroup_drain_dying
  • cgroup_rmdir
  • kernfs_iop_rmdir
  • css_killed_work_fn
  • percpu_ref_kill_and_confirm
  • pidns
  • zap_pid_ns_processes
  • /sys/fs/cgroup/
  • rmdir /sys/fs/cgroup
  • Failed to destroy cgroup
  • cgroup is not empty
  • container stop timed out
  • pod termination timed out
  • state D
  • defunct
  • <defunct>

What your security team should do

  • Prioritize patching on multi-tenant Linux hosts, container platforms, Kubernetes nodes, CI/CD runners, shared build systems, and systems that allow untrusted local code execution.
  • Inventory affected Linux kernel versions using vendor advisories and kernel package metadata; do not assume containers are protected if the underlying host kernel is vulnerable.
  • Apply the fixed kernel from the relevant distribution or vendor, then reboot hosts or verify an approved live patch is active.
  • Temporarily restrict untrusted users or workloads from creating/manipulating cgroups, PID namespaces, and privileged containers where feasible.
  • Harden container runtime policy by removing unnecessary privileges, capabilities, host namespace access, and cgroup delegation from workloads.
  • Monitor for hosts with unexplained hangs, blocked `rmdir` operations under cgroup paths, zombie accumulation, or PID 1/systemd/container-runtime processes stuck in uninterruptible sleep.
  • Treat confirmed exploitation primarily as an availability incident: isolate affected hosts, collect kernel diagnostics before reboot if possible, and restore service on patched kernels.

The record

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 packages

Ecosystem Package Introduced Fixed
openSUSE:Tumbleweed kernel-source 0 7.0.11-1.1

Related vulnerabilities