Skip to content

Commit fee7e49

Browse files
committed
mm: propagate error from stack expansion even for guard page
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 d782437: "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: Jay Foad <[email protected]> Cc: [email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent b1940cd commit fee7e49

File tree

2 files changed

+3
-3
lines changed

2 files changed

+3
-3
lines changed

include/linux/mm.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1952,7 +1952,7 @@ extern int expand_downwards(struct vm_area_struct *vma,
19521952
#if VM_GROWSUP
19531953
extern int expand_upwards(struct vm_area_struct *vma, unsigned long address);
19541954
#else
1955-
#define expand_upwards(vma, address) do { } while (0)
1955+
#define expand_upwards(vma, address) (0)
19561956
#endif
19571957

19581958
/* Look up the first VMA which satisfies addr < vm_end, NULL if none. */

mm/memory.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2593,7 +2593,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo
25932593
if (prev && prev->vm_end == address)
25942594
return prev->vm_flags & VM_GROWSDOWN ? 0 : -ENOMEM;
25952595

2596-
expand_downwards(vma, address - PAGE_SIZE);
2596+
return expand_downwards(vma, address - PAGE_SIZE);
25972597
}
25982598
if ((vma->vm_flags & VM_GROWSUP) && address + PAGE_SIZE == vma->vm_end) {
25992599
struct vm_area_struct *next = vma->vm_next;
@@ -2602,7 +2602,7 @@ static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned lo
26022602
if (next && next->vm_start == address + PAGE_SIZE)
26032603
return next->vm_flags & VM_GROWSUP ? 0 : -ENOMEM;
26042604

2605-
expand_upwards(vma, address + PAGE_SIZE);
2605+
return expand_upwards(vma, address + PAGE_SIZE);
26062606
}
26072607
return 0;
26082608
}

0 commit comments

Comments
 (0)