Merge branch 'mm-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull vmap stack fixes from Ingo Molnar:
 "This is fallout from CONFIG_HAVE_ARCH_VMAP_STACK=y on x86: stack
  accesses that used to be just somewhat questionable are now totally
  buggy.

  These changes try to do it without breaking the ABI: the fields are
  left there, they are just reporting zero, or reporting narrower
  information (the maps file change)"

* 'mm-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  mm: Change vm_is_stack_for_task() to vm_is_stack_for_current()
  fs/proc: Stop trying to report thread stacks
  fs/proc: Stop reporting eip and esp in /proc/PID/stat
  mm/numa: Remove duplicated include from mprotect.c
This commit is contained in:
Linus Torvalds 2016-10-22 09:39:10 -07:00
commit 86c5bf7101
8 changed files with 29 additions and 70 deletions

View File

@ -395,32 +395,6 @@ is not associated with a file:
or if empty, the mapping is anonymous. or if empty, the mapping is anonymous.
The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint
of the individual tasks of a process. In this file you will see a mapping marked
as [stack] if that task sees it as a stack. Hence, for the example above, the
task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this:
08048000-08049000 r-xp 00000000 03:00 8312 /opt/test
08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test
0804a000-0806b000 rw-p 00000000 00:00 0 [heap]
a7cb1000-a7cb2000 ---p 00000000 00:00 0
a7cb2000-a7eb2000 rw-p 00000000 00:00 0
a7eb2000-a7eb3000 ---p 00000000 00:00 0
a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack]
a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6
a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6
a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6
a800b000-a800e000 rw-p 00000000 00:00 0
a800e000-a8022000 r-xp 00000000 03:00 14462 /lib/libpthread.so.0
a8022000-a8023000 r--p 00013000 03:00 14462 /lib/libpthread.so.0
a8023000-a8024000 rw-p 00014000 03:00 14462 /lib/libpthread.so.0
a8024000-a8027000 rw-p 00000000 00:00 0
a8027000-a8043000 r-xp 00000000 03:00 8317 /lib/ld-linux.so.2
a8043000-a8044000 r--p 0001b000 03:00 8317 /lib/ld-linux.so.2
a8044000-a8045000 rw-p 0001c000 03:00 8317 /lib/ld-linux.so.2
aff35000-aff4a000 rw-p 00000000 00:00 0
ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
The /proc/PID/smaps is an extension based on maps, showing the memory The /proc/PID/smaps is an extension based on maps, showing the memory
consumption for each of the process's mappings. For each of mappings there consumption for each of the process's mappings. For each of mappings there
is a series of lines such as the following: is a series of lines such as the following:

View File

@ -412,10 +412,11 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
mm = get_task_mm(task); mm = get_task_mm(task);
if (mm) { if (mm) {
vsize = task_vsize(mm); vsize = task_vsize(mm);
if (permitted) { /*
eip = KSTK_EIP(task); * esp and eip are intentionally zeroed out. There is no
esp = KSTK_ESP(task); * non-racy way to read them without freezing the task.
} * Programs that need reliable values can use ptrace(2).
*/
} }
get_task_comm(tcomm, task); get_task_comm(tcomm, task);

View File

@ -266,24 +266,15 @@ static int do_maps_open(struct inode *inode, struct file *file,
* /proc/PID/maps that is the stack of the main task. * /proc/PID/maps that is the stack of the main task.
*/ */
static int is_stack(struct proc_maps_private *priv, static int is_stack(struct proc_maps_private *priv,
struct vm_area_struct *vma, int is_pid) struct vm_area_struct *vma)
{ {
int stack = 0; /*
* We make no effort to guess what a given thread considers to be
if (is_pid) { * its "stack". It's not even well-defined for programs written
stack = vma->vm_start <= vma->vm_mm->start_stack && * languages like Go.
vma->vm_end >= vma->vm_mm->start_stack; */
} else { return vma->vm_start <= vma->vm_mm->start_stack &&
struct inode *inode = priv->inode; vma->vm_end >= vma->vm_mm->start_stack;
struct task_struct *task;
rcu_read_lock();
task = pid_task(proc_pid(inode), PIDTYPE_PID);
if (task)
stack = vma_is_stack_for_task(vma, task);
rcu_read_unlock();
}
return stack;
} }
static void static void
@ -354,7 +345,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
goto done; goto done;
} }
if (is_stack(priv, vma, is_pid)) if (is_stack(priv, vma))
name = "[stack]"; name = "[stack]";
} }
@ -1669,7 +1660,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid)
seq_file_path(m, file, "\n\t= "); seq_file_path(m, file, "\n\t= ");
} else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
seq_puts(m, " heap"); seq_puts(m, " heap");
} else if (is_stack(proc_priv, vma, is_pid)) { } else if (is_stack(proc_priv, vma)) {
seq_puts(m, " stack"); seq_puts(m, " stack");
} }

View File

@ -124,25 +124,17 @@ unsigned long task_statm(struct mm_struct *mm,
} }
static int is_stack(struct proc_maps_private *priv, static int is_stack(struct proc_maps_private *priv,
struct vm_area_struct *vma, int is_pid) struct vm_area_struct *vma)
{ {
struct mm_struct *mm = vma->vm_mm; struct mm_struct *mm = vma->vm_mm;
int stack = 0;
if (is_pid) { /*
stack = vma->vm_start <= mm->start_stack && * We make no effort to guess what a given thread considers to be
vma->vm_end >= mm->start_stack; * its "stack". It's not even well-defined for programs written
} else { * languages like Go.
struct inode *inode = priv->inode; */
struct task_struct *task; return vma->vm_start <= mm->start_stack &&
vma->vm_end >= mm->start_stack;
rcu_read_lock();
task = pid_task(proc_pid(inode), PIDTYPE_PID);
if (task)
stack = vma_is_stack_for_task(vma, task);
rcu_read_unlock();
}
return stack;
} }
/* /*
@ -184,7 +176,7 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,
if (file) { if (file) {
seq_pad(m, ' '); seq_pad(m, ' ');
seq_file_path(m, file, ""); seq_file_path(m, file, "");
} else if (mm && is_stack(priv, vma, is_pid)) { } else if (mm && is_stack(priv, vma)) {
seq_pad(m, ' '); seq_pad(m, ' ');
seq_printf(m, "[stack]"); seq_printf(m, "[stack]");
} }

View File

@ -1391,7 +1391,7 @@ static inline int stack_guard_page_end(struct vm_area_struct *vma,
!vma_growsup(vma->vm_next, addr); !vma_growsup(vma->vm_next, addr);
} }
int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t); int vma_is_stack_for_current(struct vm_area_struct *vma);
extern unsigned long move_page_tables(struct vm_area_struct *vma, extern unsigned long move_page_tables(struct vm_area_struct *vma,
unsigned long old_addr, struct vm_area_struct *new_vma, unsigned long old_addr, struct vm_area_struct *new_vma,

View File

@ -25,7 +25,6 @@
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/pkeys.h> #include <linux/pkeys.h>
#include <linux/ksm.h> #include <linux/ksm.h>
#include <linux/pkeys.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>

View File

@ -230,8 +230,10 @@ void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
} }
/* Check if the vma is being used as a stack by this task */ /* Check if the vma is being used as a stack by this task */
int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t) int vma_is_stack_for_current(struct vm_area_struct *vma)
{ {
struct task_struct * __maybe_unused t = current;
return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
} }

View File

@ -3557,7 +3557,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
} else if (!vma->vm_file && } else if (!vma->vm_file &&
((vma->vm_start <= vma->vm_mm->start_stack && ((vma->vm_start <= vma->vm_mm->start_stack &&
vma->vm_end >= vma->vm_mm->start_stack) || vma->vm_end >= vma->vm_mm->start_stack) ||
vma_is_stack_for_task(vma, current))) { vma_is_stack_for_current(vma))) {
rc = current_has_perm(current, PROCESS__EXECSTACK); rc = current_has_perm(current, PROCESS__EXECSTACK);
} else if (vma->vm_file && vma->anon_vma) { } else if (vma->vm_file && vma->anon_vma) {
/* /*