aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/proc/task_mmu.c12
-rw-r--r--include/linux/mm.h24
-rw-r--r--mm/memory.c16
3 files changed, 37 insertions, 15 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 2e7addfd9803..318d8654989b 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -214,7 +214,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
214 int flags = vma->vm_flags; 214 int flags = vma->vm_flags;
215 unsigned long ino = 0; 215 unsigned long ino = 0;
216 unsigned long long pgoff = 0; 216 unsigned long long pgoff = 0;
217 unsigned long start; 217 unsigned long start, end;
218 dev_t dev = 0; 218 dev_t dev = 0;
219 int len; 219 int len;
220 220
@@ -227,13 +227,15 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
227 227
228 /* We don't show the stack guard page in /proc/maps */ 228 /* We don't show the stack guard page in /proc/maps */
229 start = vma->vm_start; 229 start = vma->vm_start;
230 if (vma->vm_flags & VM_GROWSDOWN) 230 if (stack_guard_page_start(vma, start))
231 if (!vma_stack_continue(vma->vm_prev, vma->vm_start)) 231 start += PAGE_SIZE;
232 start += PAGE_SIZE; 232 end = vma->vm_end;
233 if (stack_guard_page_end(vma, end))
234 end -= PAGE_SIZE;
233 235
234 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", 236 seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
235 start, 237 start,
236 vma->vm_end, 238 end,
237 flags & VM_READ ? 'r' : '-', 239 flags & VM_READ ? 'r' : '-',
238 flags & VM_WRITE ? 'w' : '-', 240 flags & VM_WRITE ? 'w' : '-',
239 flags & VM_EXEC ? 'x' : '-', 241 flags & VM_EXEC ? 'x' : '-',
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2348db26bc3d..6507dde38b16 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1011,11 +1011,33 @@ int set_page_dirty_lock(struct page *page);
1011int clear_page_dirty_for_io(struct page *page); 1011int clear_page_dirty_for_io(struct page *page);
1012 1012
1013/* Is the vma a continuation of the stack vma above it? */ 1013/* Is the vma a continuation of the stack vma above it? */
1014static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr) 1014static inline int vma_growsdown(struct vm_area_struct *vma, unsigned long addr)
1015{ 1015{
1016 return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN); 1016 return vma && (vma->vm_end == addr) && (vma->vm_flags & VM_GROWSDOWN);
1017} 1017}
1018 1018
1019static inline int stack_guard_page_start(struct vm_area_struct *vma,
1020 unsigned long addr)
1021{
1022 return (vma->vm_flags & VM_GROWSDOWN) &&
1023 (vma->vm_start == addr) &&
1024 !vma_growsdown(vma->vm_prev, addr);
1025}
1026
1027/* Is the vma a continuation of the stack vma below it? */
1028static inline int vma_growsup(struct vm_area_struct *vma, unsigned long addr)
1029{
1030 return vma && (vma->vm_start == addr) && (vma->vm_flags & VM_GROWSUP);
1031}
1032
1033static inline int stack_guard_page_end(struct vm_area_struct *vma,
1034 unsigned long addr)
1035{
1036 return (vma->vm_flags & VM_GROWSUP) &&
1037 (vma->vm_end == addr) &&
1038 !vma_growsup(vma->vm_next, addr);
1039}
1040
1019extern unsigned long move_page_tables(struct vm_area_struct *vma, 1041extern unsigned long move_page_tables(struct vm_area_struct *vma,
1020 unsigned long old_addr, struct vm_area_struct *new_vma, 1042 unsigned long old_addr, struct vm_area_struct *new_vma,
1021 unsigned long new_addr, unsigned long len); 1043 unsigned long new_addr, unsigned long len);
diff --git a/mm/memory.c b/mm/memory.c
index 27f425378112..61e66f026563 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1412,9 +1412,8 @@ no_page_table:
1412 1412
1413static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) 1413static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
1414{ 1414{
1415 return (vma->vm_flags & VM_GROWSDOWN) && 1415 return stack_guard_page_start(vma, addr) ||
1416 (vma->vm_start == addr) && 1416 stack_guard_page_end(vma, addr+PAGE_SIZE);
1417 !vma_stack_continue(vma->vm_prev, addr);
1418} 1417}
1419 1418
1420/** 1419/**
@@ -1551,12 +1550,6 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1551 continue; 1550 continue;
1552 } 1551 }
1553 1552
1554 /*
1555 * For mlock, just skip the stack guard page.
1556 */
1557 if ((gup_flags & FOLL_MLOCK) && stack_guard_page(vma, start))
1558 goto next_page;
1559
1560 do { 1553 do {
1561 struct page *page; 1554 struct page *page;
1562 unsigned int foll_flags = gup_flags; 1555 unsigned int foll_flags = gup_flags;
@@ -1573,6 +1566,11 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
1573 int ret; 1566 int ret;
1574 unsigned int fault_flags = 0; 1567 unsigned int fault_flags = 0;
1575 1568
1569 /* For mlock, just skip the stack guard page. */
1570 if (foll_flags & FOLL_MLOCK) {
1571 if (stack_guard_page(vma, start))
1572 goto next_page;
1573 }
1576 if (foll_flags & FOLL_WRITE) 1574 if (foll_flags & FOLL_WRITE)
1577 fault_flags |= FAULT_FLAG_WRITE; 1575 fault_flags |= FAULT_FLAG_WRITE;
1578 if (nonblocking) 1576 if (nonblocking)