lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20260106113427.20809-1-fangxiang3@xiaomi.com>
Date: Tue, 6 Jan 2026 19:34:27 +0800
From: Fang Xiang <fangxiang3@...omi.com>
To: <mingo@...hat.com>, <peterz@...radead.org>, <vincent.guittot@...aro.org>,
	<linux-kernel@...r.kernel.org>
CC: <dietmar.eggemann@....com>, <fangxiang3@...omi.com>
Subject: [PATCH] sched/fair: Fix overflow in vruntime_eligible() causing NULL return

In the vruntime_eligible() function, the original comparison:
	return avg >= (s64)(vruntime - cfs_rq->min_vruntime) * load;
could produce incorrect results due to integer overflow in the 'avg' or
s64 part.

This overflow causes the comparison to return false even when the
mathematical result should be true, leading all tasks to be falsely
deemed ineligible. Consequently, pick_eevdf() returns NULL, triggering a
kernel crash. This issue was discovered on kernel 6.6.76, it may be incorrect
to simply spot a potentially overflowing integer type and directly use
the >= sign for comparison.

The following are the relevant attributes that cause the return of NULL:
cfs_rq:
my_q = 0xFFFFFF8019BF2600 -> (
      load = (weight = 3609742336, inv_weight = 0),
      nr_running = 647,
      h_nr_running = 647,
      idle_nr_running = 0,
      idle_h_nr_running = 0,
      avg_vruntime = -13338730231239499,
      avg_load = 3525139,
      exec_clock = 598416298647,
      min_vruntime = 1918334512120,
      tasks_timeline = (
        rb_root = (rb_node = 0xFFFFFF811B63A850),
        rb_leftmost = 0xFFFFFF810C5B2850),
      )
)

root node:
 (struct sched_entity *)(0xFFFFFF811B63A850- 0x10) = 0xFFFFFF811B63A840 -> (
    load = (weight = 2561024, inv_weight = 1717300),
    run_node = (__rb_parent_color = 1, rb_right = 0xFFFFFF8054864FD0, rb_left = 0xFFFFFF8104916390),
    deadline = 1918337366679,
    min_vruntime = 18446741380279378713,
    on_rq = 1,
    sum_exec_runtime = 349968442385,
    prev_sum_exec_runtime = 349967120379,
    vruntime = 1918336679648,
 )

leftmost node:
(struct sched_entity *)(0xFFFFFF810C5B2850- 0x10) = 0xFFFFFF810C5B2840 -> (
    load = (weight = 1048576, inv_weight = 4194304),
    deadline = 18446741380282378713,
    min_vruntime = 18446741380279378713,
    on_rq = 1,
    sum_exec_runtime = 17431358323,
    prev_sum_exec_runtime = 307584686,
    vruntime = 18446741380279378713,
    vlag = 4607980805462,
 )

Signed-off-by: Fang Xiang <fangxiang3@...omi.com>
---
 kernel/sched/fair.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 726fa69c4d88..f597f8869b37 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -746,6 +746,8 @@ int entity_eligible(struct cfs_rq *cfs_rq, struct sched_entity *se)
 	struct sched_entity *curr = cfs_rq->curr;
 	s64 avg = cfs_rq->avg_vruntime;
 	long load = cfs_rq->avg_load;
+	s64 a = entity_key(cfs_rq, se);
+	s64 b, d;
 
 	if (curr && curr->on_rq) {
 		unsigned long weight = scale_load_down(curr->load.weight);
@@ -754,7 +756,11 @@ int entity_eligible(struct cfs_rq *cfs_rq, struct sched_entity *se)
 		load += weight;
 	}
 
-	return avg >= entity_key(cfs_rq, se) * load;
+	b = (s64)load;
+	if (check_mul_overflow(a, b, &d))
+		return 1;
+
+	return avg - d >= 0;
 }
 
 static u64 __update_min_vruntime(struct cfs_rq *cfs_rq, u64 vruntime)
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ