CVE-2026-99205 (GCVE-0-2026-99205)
Vulnerability from cvelistv5
Published
2026-10-28 10:35
Modified
2026-10-28 10:35
Severity ?
Summary
In the Linux kernel, the following vulnerability has been resolved: sched/core: Call wakeup_preempt() for queued tasks during class change Paul reported recent RCU changes exposed a lost resched where CPU idles with a rcutorture thread waiting while being completely runnable. Dumping the rq state at the time of idling with runnable tasks showed the following: rq->next_class = &fair_sched_class rq->nr_running = 1 rq->cfs.h_nr_queued = 0 rq->rt.rt_nr_running = 1 Although the waiting task was an RT task, "rq->next_class" did not point to rt_sched_class and was stuck at the lower priority fair_sched_class. Inspecting sched_change_end() revealed the following race with __sched_setscheduler() for queued, but non-running tasks: CPU0 CPU1 ==== ==== __schedule() /* * rq->donor is a fair task that blocks. * rq->next_class = &fair_sched_class */ rq_lock(rq0) pick_next_task() /* nr_running = 0 */ pick_task_fair() sched_balance_newidle() raw_spin_rq_unlock(rq0) rq_lock(rq0) activate_task(rq0, p) /* p is a fair task */ rq0->nr_running++; rq0->cfs.h_nr_queued++; wakeup_preempt(rq, p) rq->next_class = &fair_sched_class resched_curr() rq_unlock(rq0) __sched_setscheduler(p) /* p is moved to SCHED_RR */ task_rq_lock(p) sched_change_begin() rq0->cfs.h_nr_queued--; rq0->rt.rt_nr_running++; sched_change_end() /* * p->on_rq = 1 (ctx->queued) * but p is not rq->donor * (!ctx->running) hence * resched_curr() is and * rq->next_class upgrade is * skipped. */ task_rq_unlock() raw_spin_rq_lock(rq0) /* * rq->nr_running = 1 * rq->cfs.h_nr_queued = 0 * rq->rt.rt_nr_running = 1 * rq->next_class = &fair_sched_class */ if (rq->cfs.h_nr_queued && ...) /* Above is false */ if (rq_modified_above(this_rq, &fair_sched_class)) /* Also false since rq->next_class is still fair */ /* * sched_balance_newidle() is considered to * have failed to pull any fair tasks and no * other wakeups were detected. */ return NULL; /* pick_task_fair() */ pick_task_idle() return rq->idle; next = rq->idle; /* Preemption indicators are lost */ clear_tsk_need_resched(prev); clear_preempt_need_resched(); rq->curr = rq->idle; !!! rq->idle switches in with rq->running == 1 but !need_resched() !!! In simple words, enqueue, followed by a class change of the newly queued task goes unnoticed in rq->next_class indicator and sched_balance_newidle() sees no fair task, nor any higher priority task enqueued. The above sequence will lead to CPU idling with a runnable task on the CPU. Call wakeup_preempt() for ctx->queued cases in sched_change_end() to re-evaluate rq->next_class after class change (ENQUEUE_CLASS) and set the NEED_RESCHED indicator accordingly. Newidle balance will correctly see an enqueue of a higher priority t ---truncated---
Impacted products
Vendor Product Version
Linux Linux Version: 704069649b5bfb7bf1fe32c0281fe9036806a59a
Version: 704069649b5bfb7bf1fe32c0281fe9036806a59a
Create a notification for this product.
Show details on NVD website


{
  "containers": {
    "cna": {
      "affected": [
        {
          "defaultStatus": "unaffected",
          "product": "Linux",
          "programFiles": [
            "kernel/sched/core.c"
          ],
          "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git",
          "vendor": "Linux",
          "versions": [
            {
              "lessThan": "ae89744c5ebf299bf55ac7581768fbd9f119a903",
              "status": "affected",
              "version": "704069649b5bfb7bf1fe32c0281fe9036806a59a",
              "versionType": "git"
            },
            {
              "lessThan": "118a2cf4ced60777a2408001e2b4838fed1cea55",
              "status": "affected",
              "version": "704069649b5bfb7bf1fe32c0281fe9036806a59a",
              "versionType": "git"
            }
          ]
        },
        {
          "defaultStatus": "affected",
          "product": "Linux",
          "programFiles": [
            "kernel/sched/core.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.2.*",
              "status": "unaffected",
              "version": "7.2.13",
              "versionType": "semver"
            },
            {
              "lessThanOrEqual": "*",
              "status": "unaffected",
              "version": "7.3",
              "versionType": "original_commit_for_fix"
            }
          ]
        }
      ],
      "cpeApplicability": [
        {
          "nodes": [
            {
              "cpeMatch": [
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "7.2.13",
                  "versionStartIncluding": "7.0",
                  "vulnerable": true
                },
                {
                  "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*",
                  "versionEndExcluding": "7.3",
                  "versionStartIncluding": "7.0",
                  "vulnerable": true
                }
              ],
              "negate": false,
              "operator": "OR"
            }
          ]
        }
      ],
      "descriptions": [
        {
          "lang": "en",
          "value": "In the Linux kernel, the following vulnerability has been resolved:\n\nsched/core: Call wakeup_preempt() for queued tasks during class change\n\nPaul reported recent RCU changes exposed a lost resched where CPU idles\nwith a rcutorture thread waiting while being completely runnable.\n\nDumping the rq state at the time of idling with runnable tasks showed\nthe following:\n\n  rq-\u003enext_class = \u0026fair_sched_class\n  rq-\u003enr_running = 1\n  rq-\u003ecfs.h_nr_queued = 0\n  rq-\u003ert.rt_nr_running = 1\n\nAlthough the waiting task was an RT task, \"rq-\u003enext_class\" did not point\nto rt_sched_class and was stuck at the lower priority fair_sched_class.\n\nInspecting sched_change_end() revealed the following race with\n__sched_setscheduler() for queued, but non-running tasks:\n\n    CPU0                                   CPU1\n    ====                                   ====\n\n  __schedule()\n\n    /*\n     * rq-\u003edonor is a fair task that blocks.\n     * rq-\u003enext_class = \u0026fair_sched_class\n     */\n\n    rq_lock(rq0)\n\n    pick_next_task()\n      /* nr_running = 0 */\n      pick_task_fair()\n        sched_balance_newidle()\n          raw_spin_rq_unlock(rq0)\n                                    rq_lock(rq0)\n\n                                    activate_task(rq0, p)\n                                      /* p is a fair task */\n                                      rq0-\u003enr_running++;\n                                      rq0-\u003ecfs.h_nr_queued++;\n                                      wakeup_preempt(rq, p)\n                                        rq-\u003enext_class = \u0026fair_sched_class\n                                        resched_curr()\n\n                                    rq_unlock(rq0)\n\n                                    __sched_setscheduler(p)\n                                      /* p is moved to SCHED_RR */\n                                      task_rq_lock(p)\n                                      sched_change_begin()\n\n\t\t\t\t      rq0-\u003ecfs.h_nr_queued--;\n\t\t\t\t      rq0-\u003ert.rt_nr_running++;\n\n                                      sched_change_end()\n                                        /*\n                                         * p-\u003eon_rq = 1 (ctx-\u003equeued)\n                                         * but p is not rq-\u003edonor\n                                         * (!ctx-\u003erunning) hence\n                                         * resched_curr() is and\n                                         * rq-\u003enext_class upgrade is\n                                         * skipped.\n                                         */\n\n                                       task_rq_unlock()\n\n          raw_spin_rq_lock(rq0)\n\n          /*\n           * rq-\u003enr_running = 1\n           * rq-\u003ecfs.h_nr_queued = 0\n           * rq-\u003ert.rt_nr_running = 1\n           * rq-\u003enext_class = \u0026fair_sched_class\n           */\n\n           if (rq-\u003ecfs.h_nr_queued \u0026\u0026 ...)\n             /* Above is false */\n\n           if (rq_modified_above(this_rq, \u0026fair_sched_class))\n             /* Also false since rq-\u003enext_class is still fair */\n\n      /*\n       * sched_balance_newidle() is considered to\n       * have failed to pull any fair tasks and no\n       * other wakeups were detected.\n       */\n       return NULL; /* pick_task_fair() */\n\n    pick_task_idle()\n      return rq-\u003eidle;\n\n    next = rq-\u003eidle;\n\n    /* Preemption indicators are lost */\n    clear_tsk_need_resched(prev);\n    clear_preempt_need_resched();\n\n    rq-\u003ecurr = rq-\u003eidle;\n\n  !!! rq-\u003eidle switches in with rq-\u003erunning == 1 but !need_resched() !!!\n\nIn simple words, enqueue, followed by a class change of the newly queued\ntask goes unnoticed in rq-\u003enext_class indicator and\nsched_balance_newidle() sees no fair task, nor any higher priority task\nenqueued.\n\nThe above sequence will lead to CPU idling with a runnable task on the\nCPU.\n\nCall wakeup_preempt() for ctx-\u003equeued cases in sched_change_end() to\nre-evaluate rq-\u003enext_class after class change (ENQUEUE_CLASS) and set\nthe NEED_RESCHED indicator accordingly.\n\nNewidle balance will correctly see an enqueue of a higher priority\nt\n---truncated---"
        }
      ],
      "providerMetadata": {
        "dateUpdated": "2026-10-28T10:35:59.093Z",
        "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
        "shortName": "Linux"
      },
      "references": [
        {
          "url": "https://git.kernel.org/stable/c/ae89744c5ebf299bf55ac7581768fbd9f119a903"
        },
        {
          "url": "https://git.kernel.org/stable/c/118a2cf4ced60777a2408001e2b4838fed1cea55"
        }
      ],
      "title": "sched/core: Call wakeup_preempt() for queued tasks during class change",
      "x_generator": {
        "engine": "bippy-1.2.0"
      }
    }
  },
  "cveMetadata": {
    "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67",
    "assignerShortName": "Linux",
    "cveId": "CVE-2026-99205",
    "datePublished": "2026-10-28T10:35:59.093Z",
    "dateReserved": "2026-09-25T10:25:14.401Z",
    "dateUpdated": "2026-10-28T10:35:59.093Z",
    "state": "PUBLISHED"
  },
  "dataType": "CVE_RECORD",
  "dataVersion": "5.2"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

Sightings

Author Source Type Date

Nomenclature

  • Seen: The vulnerability was mentioned, discussed, or seen somewhere by the user.
  • Confirmed: The vulnerability is confirmed from an analyst perspective.
  • Published Proof of Concept: A public proof of concept is available for this vulnerability.
  • Exploited: This vulnerability was exploited and seen by the user reporting the sighting.
  • Patched: This vulnerability was successfully patched by the user reporting the sighting.
  • Not exploited: This vulnerability was not exploited or seen by the user reporting the sighting.
  • Not confirmed: The user expresses doubt about the veracity of the vulnerability.
  • Not patched: This vulnerability was not successfully patched by the user reporting the sighting.


Loading…

Loading…