{
  "cveId": "CVE-2026-46223",
  "url": "https://patchblox.com/security/cve/CVE-2026-46223",
  "summary": "CVE-2026-46223 is fixed in linux on 1 platform by DEBIAN-CVE-2026-46223 (version 7.0.9-1), released June 24, 2026. It is not reported as exploited. Patch Radar priority: Routine.",
  "title": "linux: In the Linux kernel, the following vulnerability has been resolved:  cgroup: Defer css percpu_ref kill on rmdir until...",
  "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\u0027s -\u003Ecss_offline() must not run while tasks are still doing kernel-side work in the cgroup.  [1] d245698d727a (\u0022cgroup: Defer task cgroup unlink until after the task is done switching out\u0022) [2] a72f73c4dd9b (\u0022cgroup: Don\u0027t expose dead tasks in cgroup\u0022) [3] 1b164b876c36 (\u0022cgroup: Wait for dying tasks to leave on rmdir\u0022) [4] 4c56a8ac6869 (\u0022cgroup: Fix cgroup_drain_dying() testing the wrong condition\u0022) [5] 13e786b64bd3 (\u0022cgroup: Increment nr_dying_subsys_* from rmdir context\u0022)  [1] moved task cset unlink from do_exit() to finish_task_switch() so a task\u0027s cset link drops only after the task has fully stopped scheduling. That made tasks past exit_signals() linger on cset-\u003Etasks 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\u0027s 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\u0027t free because PID 1 is the reaper and it\u0027s 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: -\u003Ecss_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\u0027s user-visible side then returns as soon as cgroup.procs and friends are empty, while -\u003Ecss_offline() still runs only after the cgroup is fully drained.  Verified by the original reproducer (pidns teardown \u002B 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\u0027s csets, and -\u003Ecss_offline() could fire before they drained. This patch preserves the existing synchronous behavior at that call site (kill_css_sync() \u002B 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\u0027t 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\u0027t actually broken (ordered cgroup_offline_wq \u002B 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.",
  "published": "2026-05-28T10:16:37Z",
  "severity": "medium",
  "cvss": 5.5,
  "cvssVector": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H",
  "epss": 0.00083,
  "epssPercentile": 0.00238,
  "priority": "Routine",
  "priorityTier": 4,
  "exploited": false,
  "vendorExploited": false,
  "disclosed": false,
  "fixes": [
    {
      "platform": "linux",
      "product": "linux",
      "release": "Debian 14",
      "fixedVersion": "7.0.9-1",
      "fix": "DEBIAN-CVE-2026-46223",
      "url": "https://patchblox.com/security/fix/linux/debian-cve-2026-46223",
      "released": "2026-06-24T14:07:24Z"
    }
  ],
  "noFixYet": [],
  "dataAsOf": "2026-11-08T13:06:02Z",
  "attribution": {
    "text": "Data: Patchblox Patch Radar",
    "url": "https://patchblox.com/security/patch-radar",
    "terms": "https://patchblox.com/security/patch-radar/use-the-data"
  }
}