aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2016-09-30 13:58:57 -0400
committerIngo Molnar <mingo@kernel.org>2016-10-20 03:21:41 -0400
commitb18cb64ead400c01bf1580eeba330ace51f8087d (patch)
tree2debc729e803790223c723bb4a4883f14135147f /fs/proc
parent0a1eb2d474edfe75466be6b4677ad84e5e8ca3f5 (diff)
fs/proc: Stop trying to report thread stacks
This reverts more of: b76437579d13 ("procfs: mark thread stack correctly in proc/<pid>/maps") ... which was partially reverted by: 65376df58217 ("proc: revert /proc/<pid>/maps [stack:TID] annotation") Originally, /proc/PID/task/TID/maps was the same as /proc/TID/maps. In current kernels, /proc/PID/maps (or /proc/TID/maps even for threads) shows "[stack]" for VMAs in the mm's stack address range. In contrast, /proc/PID/task/TID/maps uses KSTK_ESP to guess the target thread's stack's VMA. This is racy, probably returns garbage and, on arches with CONFIG_TASK_INFO_IN_THREAD=y, is also crash-prone: KSTK_ESP is not safe to use on tasks that aren't known to be running ordinary process-context kernel code. This patch removes the difference and just shows "[stack]" for VMAs in the mm's stack range. This is IMO much more sensible -- the actual "stack" address really is treated specially by the VM code, and the current thread stack isn't even well-defined for programs that frequently switch stacks on their own. Reported-by: Jann Horn <jann@thejh.net> Signed-off-by: Andy Lutomirski <luto@kernel.org> Acked-by: Thomas Gleixner <tglx@linutronix.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Linux API <linux-api@vger.kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tycho Andersen <tycho.andersen@canonical.com> Link: http://lkml.kernel.org/r/3e678474ec14e0a0ec34c611016753eea2e1b8ba.1475257877.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/task_mmu.c29
-rw-r--r--fs/proc/task_nommu.c28
2 files changed, 20 insertions, 37 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 6909582ce5e5..35b92d81692f 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -266,24 +266,15 @@ static int do_maps_open(struct inode *inode, struct file *file,
266 * /proc/PID/maps that is the stack of the main task. 266 * /proc/PID/maps that is the stack of the main task.
267 */ 267 */
268static int is_stack(struct proc_maps_private *priv, 268static int is_stack(struct proc_maps_private *priv,
269 struct vm_area_struct *vma, int is_pid) 269 struct vm_area_struct *vma)
270{ 270{
271 int stack = 0; 271 /*
272 272 * We make no effort to guess what a given thread considers to be
273 if (is_pid) { 273 * its "stack". It's not even well-defined for programs written
274 stack = vma->vm_start <= vma->vm_mm->start_stack && 274 * languages like Go.
275 vma->vm_end >= vma->vm_mm->start_stack; 275 */
276 } else { 276 return vma->vm_start <= vma->vm_mm->start_stack &&
277 struct inode *inode = priv->inode; 277 vma->vm_end >= vma->vm_mm->start_stack;
278 struct task_struct *task;
279
280 rcu_read_lock();
281 task = pid_task(proc_pid(inode), PIDTYPE_PID);
282 if (task)
283 stack = vma_is_stack_for_task(vma, task);
284 rcu_read_unlock();
285 }
286 return stack;
287} 278}
288 279
289static void 280static void
@@ -354,7 +345,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
354 goto done; 345 goto done;
355 } 346 }
356 347
357 if (is_stack(priv, vma, is_pid)) 348 if (is_stack(priv, vma))
358 name = "[stack]"; 349 name = "[stack]";
359 } 350 }
360 351
@@ -1669,7 +1660,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
1669 seq_file_path(m, file, "\n\t= "); 1660 seq_file_path(m, file, "\n\t= ");
1670 } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { 1661 } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
1671 seq_puts(m, " heap"); 1662 seq_puts(m, " heap");
1672 } else if (is_stack(proc_priv, vma, is_pid)) { 1663 } else if (is_stack(proc_priv, vma)) {
1673 seq_puts(m, " stack"); 1664 seq_puts(m, " stack");
1674 } 1665 }
1675 1666
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index faacb0c0d857..37175621e890 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -124,25 +124,17 @@ unsigned long task_statm(struct mm_struct *mm,
124} 124}
125 125
126static int is_stack(struct proc_maps_private *priv, 126static int is_stack(struct proc_maps_private *priv,
127 struct vm_area_struct *vma, int is_pid) 127 struct vm_area_struct *vma)
128{ 128{
129 struct mm_struct *mm = vma->vm_mm; 129 struct mm_struct *mm = vma->vm_mm;
130 int stack = 0; 130
131 131 /*
132 if (is_pid) { 132 * We make no effort to guess what a given thread considers to be
133 stack = vma->vm_start <= mm->start_stack && 133 * its "stack". It's not even well-defined for programs written
134 vma->vm_end >= mm->start_stack; 134 * languages like Go.
135 } else { 135 */
136 struct inode *inode = priv->inode; 136 return vma->vm_start <= mm->start_stack &&
137 struct task_struct *task; 137 vma->vm_end >= mm->start_stack;
138
139 rcu_read_lock();
140 task = pid_task(proc_pid(inode), PIDTYPE_PID);
141 if (task)
142 stack = vma_is_stack_for_task(vma, task);
143 rcu_read_unlock();
144 }
145 return stack;
146} 138}
147 139
148/* 140/*
@@ -184,7 +176,7 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
184 if (file) { 176 if (file) {
185 seq_pad(m, ' '); 177 seq_pad(m, ' ');
186 seq_file_path(m, file, ""); 178 seq_file_path(m, file, "");
187 } else if (mm && is_stack(priv, vma, is_pid)) { 179 } else if (mm && is_stack(priv, vma)) {
188 seq_pad(m, ' '); 180 seq_pad(m, ' ');
189 seq_printf(m, "[stack]"); 181 seq_printf(m, "[stack]");
190 } 182 }