fs/proc/task_nommu.c: don't use priv->task->mm
I do not know if CONFIG_PREEMPT/SMP is possible without CONFIG_MMU but the usage of task->mm in m_stop(). The task can exit/exec before we take mmap_sem, in this case m_stop() can hit NULL or unlock the wrong rw_semaphore. Also, this code uses priv->task != NULL to decide whether we need up_read/mmput. This is correct, but we will probably kill priv->task. Change m_start/m_stop to rely on IS_ERR_OR_NULL() like task_mmu.c does. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Cyrill Gorcunov <gorcunov@openvz.org> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Acked-by: Greg Ungerer <gerg@uclinux.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
27692cd56e
commit
47fecca15c
|
@ -217,17 +217,17 @@ static void *m_start(struct seq_file *m, loff_t *pos)
|
|||
return ERR_PTR(-ESRCH);
|
||||
|
||||
mm = priv->mm;
|
||||
if (!mm || !atomic_inc_not_zero(&mm->mm_users)) {
|
||||
put_task_struct(priv->task);
|
||||
priv->task = NULL;
|
||||
if (!mm || !atomic_inc_not_zero(&mm->mm_users))
|
||||
return NULL;
|
||||
}
|
||||
down_read(&mm->mmap_sem);
|
||||
|
||||
down_read(&mm->mmap_sem);
|
||||
/* start from the Nth VMA */
|
||||
for (p = rb_first(&mm->mm_rb); p; p = rb_next(p))
|
||||
if (n-- == 0)
|
||||
return p;
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
mmput(mm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -235,11 +235,13 @@ static void m_stop(struct seq_file *m, void *_vml)
|
|||
{
|
||||
struct proc_maps_private *priv = m->private;
|
||||
|
||||
if (!IS_ERR_OR_NULL(_vml)) {
|
||||
up_read(&priv->mm->mmap_sem);
|
||||
mmput(priv->mm);
|
||||
}
|
||||
if (priv->task) {
|
||||
struct mm_struct *mm = priv->task->mm;
|
||||
up_read(&mm->mmap_sem);
|
||||
mmput(mm);
|
||||
put_task_struct(priv->task);
|
||||
priv->task = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue