[PATCH OLK-6.6] sched/cputime: Fix time overflow in cputime_adjust()
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/8331 ------------------ When a process has hundreds of threads and runs for an extended period, the aggregated stime or utime of its thread group can become extremely large. Accessing /proc/xx/stat then triggers a divide error like the following: divide error: 0000 [#1] SMP NOPTI CPU: 273 PID: 4619 Comm: ... Tainted: 5.10.0 x86_64 RIP: 0010:cputime_adjust+0x55/0xb0 RSP: 0018:ffffae408e07bbc8 EFLAGS: 00010807 ... Call Trace: thread_group_cputime_adjusted+0x4b/0x70 do_task_stat+0x2d8/0xdc0 This is due to overflow in stime + utime, which causes mul_u64_u64_div_u64() to trigger a divide error. Add overflow detection logic and, upon overflow, right-shift the values before computation. This fixes the issue while preserving the original calculation semantics. Fixes: 3dc167ba5729 ("sched/cputime: Improve cputime_adjust()") Signed-off-by: Xia Fukun <xiafukun@huawei.com> --- kernel/sched/cputime.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index e560426f23bd..773b9411007c 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -564,6 +564,7 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, u64 *ut, u64 *st) { u64 rtime, stime, utime; + u64 s, u, sum; unsigned long flags; /* Serialize concurrent callers such that we can honour our guarantees */ @@ -599,7 +600,23 @@ void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev, goto update; } - stime = mul_u64_u64_div_u64(stime, rtime, stime + utime); + s = stime; + u = utime; + sum = s + u; + + /* + * Detect unsigned overflow: if sum < either operand, + * overflow occurred. A single right shift is sufficient + * to guarantee that the new sum won't overflow. + */ + if (unlikely(sum < s)) { + s >>= 1; + u >>= 1; + sum = s + u; + stime = mul_u64_u64_div_u64(s, rtime, sum); + } else { + stime = mul_u64_u64_div_u64(stime, rtime, stime + utime); + } /* * Because mul_u64_u64_div_u64() can approximate on some * achitectures; enforce the constraint that: a*b/(b+c) <= a. -- 2.34.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/23316 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/WOT... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/23316 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/WOT...
participants (2)
-
patchwork bot -
Xia Fukun