Commit 288a07dd authored by Linus Torvalds's avatar Linus Torvalds Committed by Zefan Li

mm: propagate error from stack expansion even for guard page

commit fee7e49d upstream.

Jay Foad reports that the address sanitizer test (asan) sometimes gets
confused by a stack pointer that ends up being outside the stack vma
that is reported by /proc/maps.

This happens due to an interaction between RLIMIT_STACK and the guard
page: when we do the guard page check, we ignore the potential error
from the stack expansion, which effectively results in a missing guard
page, since the expected stack expansion won't have been done.

And since /proc/maps explicitly ignores the guard page (commit
d7824370: "mm: fix up some user-visible effects of the stack guard
page"), the stack pointer ends up being outside the reported stack area.

This is the minimal patch: it just propagates the error.  It also
effectively makes the guard page part of the stack limit, which in turn
measn that the actual real stack is one page less than the stack limit.

Let's see if anybody notices.  We could teach acct_stack_growth() to
allow an extra page for a grow-up/grow-down stack in the rlimit test,
but I don't want to add more complexity if it isn't needed.
Reported-and-tested-by: default avatarJay Foad <jay.foad@gmail.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarZefan Li <lizefan@huawei.com>
parent 58250a5c
...@@ -1456,7 +1456,7 @@ extern int expand_downwards(struct vm_area_struct *vma, ...@@ -1456,7 +1456,7 @@ extern int expand_downwards(struct vm_area_struct *vma,
#if VM_GROWSUP #if VM_GROWSUP
extern int expand_upwards(struct vm_area_struct *vma, unsigned long address); extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
#else #else
#define expand_upwards(vma, address) do { } while (0) #define expand_upwards(vma, address) (0)
#endif #endif
/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */ /* Look up the first VMA which satisfies addr < vm_end, NULL if none. */
......
...@@ -3137,7 +3137,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo ...@@ -3137,7 +3137,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo
if (prev && prev->vm_end == address) if (prev && prev->vm_end == address)
return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM; return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
expand_downwards(vma, address - PAGE_SIZE); return expand_downwards(vma, address - PAGE_SIZE);
} }
if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) { if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
struct vm_area_struct *next = vma->vm_next; struct vm_area_struct *next = vma->vm_next;
...@@ -3146,7 +3146,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo ...@@ -3146,7 +3146,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo
if (next && next->vm_start == address + PAGE_SIZE) if (next && next->vm_start == address + PAGE_SIZE)
return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM; return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
expand_upwards(vma, address + PAGE_SIZE); return expand_upwards(vma, address + PAGE_SIZE);
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment