[PATCH] MIPS: Ensure VDSO pages mapped above STACK_TOP

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Unlimited stack size (ulimit -s unlimited) causes kernel to use legacy
layout for applications. Thus, if VDSO isn't mapped above STACK_TOP, it
will be mapped at a very low address. This will probably cause an early
brk() failure and then a segmentation fault, because the application's
initial mm->brk is usually below VDSO (especially when COMPAT_BRK is
enabled) and there is no more room to expand its heap.

This patch reserve 4 MB space above STACK_TOP, and use the low 2 MB for
VDSO randomization (as a result, VDSO pages can use as much as 2 MB).

Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Huacai Chen <chenhc@xxxxxxxxxx>
---
 arch/mips/include/asm/processor.h |  5 +++--
 arch/mips/kernel/vdso.c           | 16 +++++++++++++++-
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h
index 95b8c47..1c99e2c 100644
--- a/arch/mips/include/asm/processor.h
+++ b/arch/mips/include/asm/processor.h
@@ -13,6 +13,7 @@
 
 #include <linux/atomic.h>
 #include <linux/cpumask.h>
+#include <linux/sizes.h>
 #include <linux/threads.h>
 
 #include <asm/cachectl.h>
@@ -82,9 +83,9 @@ extern unsigned int vced_count, vcei_count;
 
 /*
  * One page above the stack is used for branch delay slot "emulation".
- * See dsemul.c for details.
+ * See dsemul.c for details, other pages are for VDSO.
  */
-#define STACK_TOP	((TASK_SIZE & PAGE_MASK) - PAGE_SIZE)
+#define STACK_TOP	((TASK_SIZE & PAGE_MASK) - SZ_4M)
 
 /*
  * This decides where the kernel will search for a free chunk of vm
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 093517e..71fecec 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -15,6 +15,7 @@
 #include <linux/ioport.h>
 #include <linux/irqchip/mips-gic.h>
 #include <linux/mm.h>
+#include <linux/random.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/timekeeper_internal.h>
@@ -95,6 +96,19 @@ void update_vsyscall_tz(void)
 	}
 }
 
+static unsigned long vdso_base(void)
+{
+	unsigned long offset = 0UL;
+
+	if (current->flags & PF_RANDOMIZE) {
+		offset = get_random_int();
+		offset <<= PAGE_SHIFT;
+		offset &= 0x1ffffful; /* 2 MB */
+	}
+
+	return STACK_TOP + PAGE_SIZE + offset;
+}
+
 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 {
 	struct mips_vdso_image *image = current->thread.abi->vdso;
@@ -129,7 +143,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 	vvar_size = gic_size + PAGE_SIZE;
 	size = vvar_size + image->size;
 
-	base = get_unmapped_area(NULL, 0, size, 0, 0);
+	base = get_unmapped_area(NULL, vdso_base(), size, 0, 0);
 	if (IS_ERR_VALUE(base)) {
 		ret = base;
 		goto out;
-- 
2.7.0






[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]