cgroup: css_task_iter_skip()’d iterators must be advanced before accessed [Linux 4.19.66]

This Linux kernel change "cgroup: css_task_iter_skip()’d iterators must be advanced before accessed" is included in the Linux 4.19.66 release. This change is authored by Tejun Heo <tj [at] kernel.org> on Wed Jun 5 09:54:34 2019 -0700. The commit for this change in Linux stable tree is 0a9abd2 (patch) which is from upstream commit cee0c33. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream cee0c33.

cgroup: css_task_iter_skip()'d iterators must be advanced before accessed

commit cee0c33c546a93957a52ae9ab6bebadbee765ec5 upstream.

b636fd38dc40 ("cgroup: Implement css_task_iter_skip()") introduced
css_task_iter_skip() which is used to fix task iterations skipping
dying threadgroup leaders with live threads.  Skipping is implemented
as a subportion of full advancing but css_task_iter_next() forgot to
fully advance a skipped iterator before determining the next task to
visit causing it to return invalid task pointers.

Fix it by making css_task_iter_next() fully advance the iterator if it
has been skipped since the previous iteration.

Signed-off-by: Tejun Heo <[email protected]>
Reported-by: syzbot
Link: http://lkml.kernel.org/r/[email protected]
Fixes: b636fd38dc40 ("cgroup: Implement css_task_iter_skip()")
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 4 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 kernel/cgroup/cgroup.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c
index 89dd464..ddde75b 100644
--- a/kernel/cgroup/cgroup.c
+++ b/kernel/cgroup/cgroup.c
@@ -4303,6 +4303,10 @@ struct task_struct *css_task_iter_next(struct css_task_iter *it)

    spin_lock_irq(&css_set_lock);

+   /* @it may be half-advanced by skips, finish advancing */
+   if (it->flags & CSS_TASK_ITER_SKIPPED)
+       css_task_iter_advance(it);
+
    if (it->task_pos) {
        it->cur_task = list_entry(it->task_pos, struct task_struct,
                      cg_list);

Leave a Reply

Your email address will not be published. Required fields are marked *