Skip to content

Commit ec5164c

Browse files
committed
Merge: fs/proc: do_task_stat: use sig->stats_lock to gather the threads/children stats
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/4497 JIRA: https://issues.redhat.com/browse/RHEL-31564 Upstream Status: linux.git CVE: CVE-2024-26686 Signed-off-by: Brian Foster <bfoster@redhat.com> Approved-by: Rafael Aquini <aquini@redhat.com> Approved-by: Herton R. Krzesinski <herton@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Lucas Zampieri <lzampier@redhat.com>
2 parents e25f702 + 0bd3a41 commit ec5164c

File tree

1 file changed

+37
-28
lines changed

1 file changed

+37
-28
lines changed

fs/proc/array.c

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -485,13 +485,13 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
485485
int permitted;
486486
struct mm_struct *mm;
487487
unsigned long long start_time;
488-
unsigned long cmin_flt = 0, cmaj_flt = 0;
489-
unsigned long min_flt = 0, maj_flt = 0;
490-
u64 cutime, cstime, utime, stime;
491-
u64 cgtime, gtime;
488+
unsigned long cmin_flt, cmaj_flt, min_flt, maj_flt;
489+
u64 cutime, cstime, cgtime, utime, stime, gtime;
492490
unsigned long rsslim = 0;
493491
unsigned long flags;
494492
int exit_code = task->exit_code;
493+
struct signal_struct *sig = task->signal;
494+
unsigned int seq = 1;
495495

496496
state = *get_task_state(task);
497497
vsize = eip = esp = 0;
@@ -519,12 +519,8 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
519519

520520
sigemptyset(&sigign);
521521
sigemptyset(&sigcatch);
522-
cutime = cstime = utime = stime = 0;
523-
cgtime = gtime = 0;
524522

525523
if (lock_task_sighand(task, &flags)) {
526-
struct signal_struct *sig = task->signal;
527-
528524
if (sig->tty) {
529525
struct pid *pgrp = tty_get_pgrp(sig->tty);
530526
tty_pgrp = pid_nr_ns(pgrp, ns);
@@ -535,27 +531,9 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
535531
num_threads = get_nr_threads(task);
536532
collect_sigign_sigcatch(task, &sigign, &sigcatch);
537533

538-
cmin_flt = sig->cmin_flt;
539-
cmaj_flt = sig->cmaj_flt;
540-
cutime = sig->cutime;
541-
cstime = sig->cstime;
542-
cgtime = sig->cgtime;
543534
rsslim = READ_ONCE(sig->rlim[RLIMIT_RSS].rlim_cur);
544535

545-
/* add up live thread stats at the group level */
546536
if (whole) {
547-
struct task_struct *t = task;
548-
do {
549-
min_flt += t->min_flt;
550-
maj_flt += t->maj_flt;
551-
gtime += task_gtime(t);
552-
} while_each_thread(task, t);
553-
554-
min_flt += sig->min_flt;
555-
maj_flt += sig->maj_flt;
556-
thread_group_cputime_adjusted(task, &utime, &stime);
557-
gtime += sig->gtime;
558-
559537
if (sig->flags & (SIGNAL_GROUP_EXIT | SIGNAL_STOP_STOPPED))
560538
exit_code = sig->group_exit_code;
561539
}
@@ -569,10 +547,41 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
569547

570548
if (permitted && (!whole || num_threads < 2))
571549
wchan = !task_is_running(task);
572-
if (!whole) {
550+
551+
do {
552+
seq++; /* 2 on the 1st/lockless path, otherwise odd */
553+
flags = read_seqbegin_or_lock_irqsave(&sig->stats_lock, &seq);
554+
555+
cmin_flt = sig->cmin_flt;
556+
cmaj_flt = sig->cmaj_flt;
557+
cutime = sig->cutime;
558+
cstime = sig->cstime;
559+
cgtime = sig->cgtime;
560+
561+
if (whole) {
562+
struct task_struct *t;
563+
564+
min_flt = sig->min_flt;
565+
maj_flt = sig->maj_flt;
566+
gtime = sig->gtime;
567+
568+
rcu_read_lock();
569+
__for_each_thread(sig, t) {
570+
min_flt += t->min_flt;
571+
maj_flt += t->maj_flt;
572+
gtime += task_gtime(t);
573+
}
574+
rcu_read_unlock();
575+
}
576+
} while (need_seqretry(&sig->stats_lock, seq));
577+
done_seqretry_irqrestore(&sig->stats_lock, seq, flags);
578+
579+
if (whole) {
580+
thread_group_cputime_adjusted(task, &utime, &stime);
581+
} else {
582+
task_cputime_adjusted(task, &utime, &stime);
573583
min_flt = task->min_flt;
574584
maj_flt = task->maj_flt;
575-
task_cputime_adjusted(task, &utime, &stime);
576585
gtime = task_gtime(task);
577586
}
578587

0 commit comments

Comments
 (0)