[<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