| From bc9155782c11dcb0975d07c54fbbd483e635ad9b Mon Sep 17 00:00:00 2001 |
| From: Vasily Averin <vvs@virtuozzo.com> |
| Date: Thu, 30 Jan 2020 13:34:59 +0300 |
| Subject: [PATCH] cgroup: cgroup_procs_next should increase position index |
| |
| commit 2d4ecb030dcc90fb725ecbfc82ce5d6c37906e0e upstream. |
| |
| If seq_file .next fuction does not change position index, |
| read after some lseek can generate unexpected output: |
| |
| 1) dd bs=1 skip output of each 2nd elements |
| $ dd if=/sys/fs/cgroup/cgroup.procs bs=8 count=1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 1+0 records in |
| 1+0 records out |
| 8 bytes copied, 0,000267297 s, 29,9 kB/s |
| [test@localhost ~]$ dd if=/sys/fs/cgroup/cgroup.procs bs=1 count=8 |
| 2 |
| 4 <<< NB! 3 was skipped |
| 6 <<< ... and 5 too |
| 8 <<< ... and 7 |
| 8+0 records in |
| 8+0 records out |
| 8 bytes copied, 5,2123e-05 s, 153 kB/s |
| |
| This happen because __cgroup_procs_start() makes an extra |
| extra cgroup_procs_next() call |
| |
| 2) read after lseek beyond end of file generates whole last line. |
| 3) read after lseek into middle of last line generates |
| expected rest of last line and unexpected whole line once again. |
| |
| Additionally patch removes an extra position index changes in |
| __cgroup_procs_start() |
| |
| Cc: stable@vger.kernel.org |
| https://bugzilla.kernel.org/show_bug.cgi?id=206283 |
| Signed-off-by: Vasily Averin <vvs@virtuozzo.com> |
| Signed-off-by: Tejun Heo <tj@kernel.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c |
| index 1c28cdb921bc..f0a11e734bae 100644 |
| --- a/kernel/cgroup/cgroup.c |
| +++ b/kernel/cgroup/cgroup.c |
| @@ -4615,6 +4615,9 @@ static void *cgroup_procs_next(struct seq_file *s, void *v, loff_t *pos) |
| struct kernfs_open_file *of = s->private; |
| struct css_task_iter *it = of->priv; |
| |
| + if (pos) |
| + (*pos)++; |
| + |
| return css_task_iter_next(it); |
| } |
| |
| @@ -4630,7 +4633,7 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos, |
| * from position 0, so we can simply keep iterating on !0 *pos. |
| */ |
| if (!it) { |
| - if (WARN_ON_ONCE((*pos)++)) |
| + if (WARN_ON_ONCE((*pos))) |
| return ERR_PTR(-EINVAL); |
| |
| it = kzalloc(sizeof(*it), GFP_KERNEL); |
| @@ -4638,10 +4641,11 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos, |
| return ERR_PTR(-ENOMEM); |
| of->priv = it; |
| css_task_iter_start(&cgrp->self, iter_flags, it); |
| - } else if (!(*pos)++) { |
| + } else if (!(*pos)) { |
| css_task_iter_end(it); |
| css_task_iter_start(&cgrp->self, iter_flags, it); |
| - } |
| + } else |
| + return it->cur_task; |
| |
| return cgroup_procs_next(s, NULL, NULL); |
| } |
| -- |
| 2.7.4 |
| |