@@ -787,6 +787,10 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_ip,
#define __TASK_UNMAPPED_BASE(task_size) (PAGE_ALIGN(task_size / 3))
#define TASK_UNMAPPED_BASE __TASK_UNMAPPED_BASE(TASK_SIZE_LOW)
+#ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES
+#define TASK_UNMAPPED_COMPAT_BASE __TASK_UNMAPPED_BASE(task_size_32bit())
+#endif
+
#define KSTK_EIP(task) (task_pt_regs(task)->ip)
/* Get/set a process' ability to use the timestamp counter instruction */
@@ -357,8 +357,9 @@ unsigned long arch_mmap_rnd(void)
{
unsigned long rnd;
-#ifdef CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS
- if (is_compat_task())
+#if defined(CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS) \
+ || defined(CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES)
+ if (is_compat_task() || in_compat_syscall())
rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1);
else
#endif /* CONFIG_HAVE_ARCH_MMAP_RND_COMPAT_BITS */
@@ -422,6 +423,22 @@ void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)
mm->mmap_base = mmap_base(random_factor, STACK_TOP, rlim_stack);
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
+#ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES
+ /*
+ * The mmap syscall mapping base decision depends solely on the
+ * syscall type (64-bit or compat). This applies for 64bit
+ * applications and 32bit applications. The 64bit syscall uses
+ * mmap_base, the compat syscall uses mmap_compat_base.
+ */
+ if (mmap_is_legacy(rlim_stack)) {
+ mm->mmap_compat_legacy_base =
+ TASK_UNMAPPED_COMPAT_BASE + random_factor;
+ mm->mmap_compat_base = mm->mmap_compat_legacy_base;
+ } else {
+ mm->mmap_compat_base = mmap_base(random_factor,
+ task_size_32bit(), rlim_stack);
+ }
+#endif
}
#elif defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT)
void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack)