s390/mmap: take stack_guard_gap into account for mmap_base
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 29 Jan 2019 09:48:09 +0000 (10:48 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 7 Feb 2019 10:57:01 +0000 (11:57 +0100)
The s390 version of the mmap_base function is ignorant of stack_guard_gap
which can lead to a placement of the stack vs. the mmap base that does not
leave enough space for the stack rlimit.

Add the stack_guard_gap to the calculation and while we are at it the
check for gap+pad overflows as well.

Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/mm/mmap.c

index 0a7627c..687f2a4 100644 (file)
@@ -29,14 +29,6 @@ static unsigned long stack_maxrandom_size(void)
        return STACK_RND_MASK << PAGE_SHIFT;
 }
 
-/*
- * Top of mmap area (just below the process stack).
- *
- * Leave at least a ~32 MB hole.
- */
-#define MIN_GAP (32*1024*1024)
-#define MAX_GAP (STACK_TOP/6*5)
-
 static inline int mmap_is_legacy(struct rlimit *rlim_stack)
 {
        if (current->personality & ADDR_COMPAT_LAYOUT)
@@ -60,13 +52,26 @@ static inline unsigned long mmap_base(unsigned long rnd,
                                      struct rlimit *rlim_stack)
 {
        unsigned long gap = rlim_stack->rlim_cur;
+       unsigned long pad = stack_maxrandom_size() + stack_guard_gap;
+       unsigned long gap_min, gap_max;
+
+       /* Values close to RLIM_INFINITY can overflow. */
+       if (gap + pad > gap)
+               gap += pad;
+
+       /*
+        * Top of mmap area (just below the process stack).
+        * Leave at least a ~32 MB hole.
+        */
+       gap_min = 32 * 1024 * 1024UL;
+       gap_max = (STACK_TOP / 6) * 5;
+
+       if (gap < gap_min)
+               gap = gap_min;
+       else if (gap > gap_max)
+               gap = gap_max;
 
-       if (gap < MIN_GAP)
-               gap = MIN_GAP;
-       else if (gap > MAX_GAP)
-               gap = MAX_GAP;
-       gap &= PAGE_MASK;
-       return STACK_TOP - stack_maxrandom_size() - rnd - gap;
+       return PAGE_ALIGN(STACK_TOP - gap - rnd);
 }
 
 unsigned long