{
  "affected": [
    {
      "ranges": [
        {
          "events": [
            {
              "introduced": "260fbcb92bbeacfcd050410fdc2d24ab15044400"
            },
            {
              "fixed": "828938118d6c2bb711301748c3e39e4bed6a62f5"
            },
            {
              "fixed": "057dac23d329d5c5ed62352f2659a39fd46c6d4a"
            }
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "type": "GIT"
        }
      ]
    },
    {
      "package": {
        "ecosystem": "Linux",
        "name": "Kernel"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "6.19.0"
            },
            {
              "fixed": "7.2.8"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "database_specific": {
    "cna_assigner": "Linux",
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/98xxx/CVE-2026-98163.json"
  },
  "details": "In the Linux kernel, the following vulnerability has been resolved:\n\ncgroup: Avoid iteration of dying tasks with zero refcount\n\nThe commit 260fbcb92bbea (\"cgroup: Move dying_tasks cleanup from\ncgroup_task_release() to cgroup_task_free()\") extended the lifetime of\ntasks on the dying_tasks list.\nThe iterators have provision to go through dying_tasks because of\ndying threadgroup leaders or explicit CSS_TASK_ITER_WITH_DEAD, however,\nit was expected that such tasks can obtain a new reference (that is\npossible before cgroup_task_release()/put_task_struct_rcu_user()).\nThe tasks after cgroup_task_release() and before cgroup_task_free()\nare subject to race when they may or may not have -\u003eusage count \u003e 0.\n\nThe race window is between css_task_iter_next() invocations\nwhen css_set_lock is released and we may arrive at a new -\u003etask_pos.\nThe iterator should not attempt to resurrect tasks whose -\u003eusage count\ndropped to zero. (When that happens, __put_task_struct_rcu_cb() is\nalready imminent and the returned task_struct would could be used\nafter free.)\n\nAs for the fix, we cannot simply check the signal-\u003elive count of a task\non the dying list because that won't distinguish regular zombies waiting\nto be reaped from RCU remnant tasks that are going to be free'd.\nTherefore add an extra check to rule out -\u003eusage==0 tasks from any\niteration.\n\nThe repeat: loop in css_task_iter_advance() doesn't consider -\u003eusage\ncount, so add a new loop to css_task_iter_next() to skip de-used tasks\non the dying_list.\n\nRough illustration of the possible race\n\n  R (reader of cgroup.procs)         T (thread)                       L (group leader)\n  ---------------------------------  -------------------------------- --------------------------------\n                                                                      L exits, signal-\u003elive \u003e 0\n                                                                      cgroup_task_dead(L)\n                                                                        css_set_skip_task_iters() // skips only cset-\u003etasks\n                                                                        list_add_tail(\u0026L-\u003ecg_list, \u0026cset-\u003edying_tasks)\n  css_task_iter_next()\n    take css_set_lock\n    css_task_iter_advance()\n      leader \u0026\u0026 signal-\u003elive != 0\n      =\u003e it-\u003etask_pos = \u0026L-\u003ecg_list\n    release css_set_lock\n                                     T exits\n                                     --signal-\u003elive == 0\n\t\t\t\t     cgroup_task_dead(T) // css_set_lock\n                                     release_task(T)\n                                       cgroup_task_release(T)\n                                       release_task(L) // zap_leader\n                                         cgroup_task_release(L)\n                                         put_task_struct_rcu_user(L)\n                                         ...RCU...\n                                         put_task_struct(L)\n                                           L-\u003eusage = 0\n                                           /* L still on dying_tasks */\n                                           ...RCU...\n                                           __put_task_struct(L)\n  css_task_iter_next() // another iteration\n    take css_set_lock\n    it-\u003etask_pos = \u0026L-\u003ecg_list\n    get_task_struct(L)\n      =\u003e addition on 0\n    drop css_set_lock\n                                           cgroup_task_free(L)\n                                             css_set_skip_task_iters() // dying skip comes too late\n                                           free_task(L)\n  cgroup_procs_show()\n    task_pid_vnr(L)",
  "id": "CVE-2026-98163",
  "modified": "2026-09-28T03:30:36.299830033Z",
  "published": "2026-09-26T08:31:50.899Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/057dac23d329d5c5ed62352f2659a39fd46c6d4a"
    },
    {
      "type": "WEB",
      "url": "https://git.kernel.org/stable/c/828938118d6c2bb711301748c3e39e4bed6a62f5"
    },
    {
      "type": "ADVISORY",
      "url": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/98xxx/CVE-2026-98163.json"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-98163"
    },
    {
      "type": "PACKAGE",
      "url": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git"
    }
  ],
  "schema_version": "1.9.0",
  "summary": "cgroup: Avoid iteration of dying tasks with zero refcount"
}