| From 84ed37ad33c2b841bfb7051cb032dd79f049e351 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 15 Sep 2023 12:00:56 -0400 |
| Subject: proc: nommu: fix empty /proc/<pid>/maps |
| |
| From: Ben Wolsieffer <ben.wolsieffer@hefring.com> |
| |
| [ Upstream commit fe4419801617514765974f3e796269bc512ad146 ] |
| |
| On no-MMU, /proc/<pid>/maps reads as an empty file. This happens because |
| find_vma(mm, 0) always returns NULL (assuming no vma actually contains the |
| zero address, which is normally the case). |
| |
| To fix this bug and improve the maintainability in the future, this patch |
| makes the no-MMU implementation as similar as possible to the MMU |
| implementation. |
| |
| The only remaining differences are the lack of hold/release_task_mempolicy |
| and the extra code to shoehorn the gate vma into the iterator. |
| |
| This has been tested on top of 6.5.3 on an STM32F746. |
| |
| Link: https://lkml.kernel.org/r/20230915160055.971059-2-ben.wolsieffer@hefring.com |
| Fixes: 0c563f148043 ("proc: remove VMA rbtree use from nommu") |
| Signed-off-by: Ben Wolsieffer <ben.wolsieffer@hefring.com> |
| Cc: Davidlohr Bueso <dave@stgolabs.net> |
| Cc: Giulio Benetti <giulio.benetti@benettiengineering.com> |
| Cc: Liam R. Howlett <Liam.Howlett@oracle.com> |
| Cc: Matthew Wilcox (Oracle) <willy@infradead.org> |
| Cc: Oleg Nesterov <oleg@redhat.com> |
| Cc: Vlastimil Babka <vbabka@suse.cz> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/proc/internal.h | 2 -- |
| fs/proc/task_nommu.c | 37 ++++++++++++++++++++++--------------- |
| 2 files changed, 22 insertions(+), 17 deletions(-) |
| |
| diff --git a/fs/proc/internal.h b/fs/proc/internal.h |
| index 9dda7e54b2d0d..9a8f32f21ff56 100644 |
| --- a/fs/proc/internal.h |
| +++ b/fs/proc/internal.h |
| @@ -289,9 +289,7 @@ struct proc_maps_private { |
| struct inode *inode; |
| struct task_struct *task; |
| struct mm_struct *mm; |
| -#ifdef CONFIG_MMU |
| struct vma_iterator iter; |
| -#endif |
| #ifdef CONFIG_NUMA |
| struct mempolicy *task_mempolicy; |
| #endif |
| diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c |
| index 061bd3f82756e..d3e19080df4af 100644 |
| --- a/fs/proc/task_nommu.c |
| +++ b/fs/proc/task_nommu.c |
| @@ -188,15 +188,28 @@ static int show_map(struct seq_file *m, void *_p) |
| return nommu_vma_show(m, _p); |
| } |
| |
| -static void *m_start(struct seq_file *m, loff_t *pos) |
| +static struct vm_area_struct *proc_get_vma(struct proc_maps_private *priv, |
| + loff_t *ppos) |
| +{ |
| + struct vm_area_struct *vma = vma_next(&priv->iter); |
| + |
| + if (vma) { |
| + *ppos = vma->vm_start; |
| + } else { |
| + *ppos = -1UL; |
| + } |
| + |
| + return vma; |
| +} |
| + |
| +static void *m_start(struct seq_file *m, loff_t *ppos) |
| { |
| struct proc_maps_private *priv = m->private; |
| + unsigned long last_addr = *ppos; |
| struct mm_struct *mm; |
| - struct vm_area_struct *vma; |
| - unsigned long addr = *pos; |
| |
| - /* See m_next(). Zero at the start or after lseek. */ |
| - if (addr == -1UL) |
| + /* See proc_get_vma(). Zero at the start or after lseek. */ |
| + if (last_addr == -1UL) |
| return NULL; |
| |
| /* pin the task and mm whilst we play with them */ |
| @@ -218,12 +231,9 @@ static void *m_start(struct seq_file *m, loff_t *pos) |
| return ERR_PTR(-EINTR); |
| } |
| |
| - /* start the next element from addr */ |
| - vma = find_vma(mm, addr); |
| - if (vma) |
| - return vma; |
| + vma_iter_init(&priv->iter, mm, last_addr); |
| |
| - return NULL; |
| + return proc_get_vma(priv, ppos); |
| } |
| |
| static void m_stop(struct seq_file *m, void *v) |
| @@ -240,12 +250,9 @@ static void m_stop(struct seq_file *m, void *v) |
| priv->task = NULL; |
| } |
| |
| -static void *m_next(struct seq_file *m, void *_p, loff_t *pos) |
| +static void *m_next(struct seq_file *m, void *_p, loff_t *ppos) |
| { |
| - struct vm_area_struct *vma = _p; |
| - |
| - *pos = vma->vm_end; |
| - return find_vma(vma->vm_mm, vma->vm_end); |
| + return proc_get_vma(m->private, ppos); |
| } |
| |
| static const struct seq_operations proc_pid_maps_ops = { |
| -- |
| 2.40.1 |
| |