diff options
| -rw-r--r-- | fs/proc/task_mmu.c | 12 | ||||
| -rw-r--r-- | include/linux/mm.h | 24 | ||||
| -rw-r--r-- | mm/memory.c | 16 |
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); | |||
| 1011 | int clear_page_dirty_for_io(struct page *page); | 1011 | int 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? */ |
| 1014 | static inline int vma_stack_continue(struct vm_area_struct *vma, unsigned long addr) | 1014 | static 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 | ||
| 1019 | static 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? */ | ||
| 1028 | static 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 | |||
| 1033 | static 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 | |||
| 1019 | extern unsigned long move_page_tables(struct vm_area_struct *vma, | 1041 | extern 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 | ||
| 1413 | static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr) | 1413 | static 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) |
