MM fixes
Subsystems (6)
Linus,
Please pull the latest mm-urgent-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git mm-urgent-for-linus
# HEAD: d17af5056cf9e9fc05e68832f7c15687fcc12281 mm: Change vm_is_stack_for_task() to vm_is_stack_for_current()
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).
Thanks,
Ingo
------------------>
Andy Lutomirski (3):
fs/proc: Stop reporting eip and esp in /proc/PID/stat fs/proc: Stop trying to report thread stacks
mm: Change vm_is_stack_for_task() to vm_is_stack_for_current()
Wei Yongjun (1):
mm/numa: Remove duplicated include from mprotect.c
Documentation/filesystems/proc.txt | 26 -------------------------- fs/proc/array.c | 9 +++++---- fs/proc/task_mmu.c | 29 ++++++++++------------------- fs/proc/task_nommu.c | 28 ++++++++++------------------ include/linux/mm.h | 2 +- mm/mprotect.c | 1 - mm/util.c | 4 +++- security/selinux/hooks.c | 2 +- 8 files changed, 30 insertions(+), 71 deletions(-)
Documentation/filesystems/proc.txt +0 -26
@@ -395,32 +395,6 @@ The "pathname" shows the name associated file for this mapping. If the mapping 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 consumption for each of the process's mappings. For each of mappings there is a series of lines such as the following:
fs/proc/array.c +5 -4
@@ -412,10 +412,11 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, mm =get_task_mm (task);if (mm) { vsize =task_vsize (mm); -if (permitted) { - eip =KSTK_EIP (task); - esp =KSTK_ESP (task); - } +/* +* esp and eip are intentionally zeroed out. There is no +* non-racy way to read them without freezing the task. +* Programs that need reliable values can use ptrace(2). +*/ }get_task_comm (tcomm, task);
fs/proc/task_mmu.c +10 -19
@@ -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. */ 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 ; - -if (is_pid) { - stack = vma->vm_start <= vma->vm_mm->start_stack && - vma->vm_end >= vma->vm_mm->start_stack; - }else { -struct inode *inode = priv->inode; -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; +/* +* We make no effort to guess what a given thread considers to be +* its "stack". It's not even well-defined for programs written +* languages like Go. +*/ +return vma->vm_start <= vma->vm_mm->start_stack && + vma->vm_end >= vma->vm_mm->start_stack; } static void
@@ -354,7 +345,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) goto done; } -if (is_stack (priv, vma, is_pid)) +if (is_stack (priv, vma)) 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= " ); }else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {seq_puts (m," heap" ); - }else if (is_stack (proc_priv, vma, is_pid)) { + }else if (is_stack (proc_priv, vma)) {seq_puts (m," stack" ); }
fs/proc/task_nommu.c +10 -18
@@ -124,25 +124,17 @@ unsigned long task_statm(struct mm_struct *mm, }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; -int stack =0 ; - -if (is_pid) { - stack = vma->vm_start <= mm->start_stack && - vma->vm_end >= mm->start_stack; - }else { -struct inode *inode = priv->inode; -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; + +/* +* We make no effort to guess what a given thread considers to be +* its "stack". It's not even well-defined for programs written +* languages like Go. +*/ +return vma->vm_start <= mm->start_stack && + vma->vm_end >= mm->start_stack; }/*
@@ -184,7 +176,7 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,if (file) {seq_pad (m,' ' );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_printf (m,"[stack]" ); }
include/linux/mm.h +1 -1
@@ -1391,7 +1391,7 @@ static inline int stack_guard_page_end(struct vm_area_struct *vma, !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, unsigned long old_addr, struct vm_area_struct *new_vma,
mm/mprotect.c +0 -1
@@ -25,7 +25,6 @@#include <linux/perf_event.h> #include <linux/pkeys.h> #include <linux/ksm.h> -#include <linux/pkeys.h> #include <asm/uaccess.h> #include <asm/pgtable.h> #include <asm/cacheflush.h>
mm/util.c +3 -1
@@ -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 */ -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)); }
security/selinux/hooks.c +1 -1
@@ -3557,7 +3557,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, }else if (!vma->vm_file && ((vma->vm_start <= 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 ); }else if (vma->vm_file && vma->anon_vma) {/*