[PATCH v2 3/6] mm/util: Support CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES
From: sxwjean
Date: Mon Oct 11 2021 - 10:34:25 EST
From: Xiongwei Song <sxwjean@xxxxxxxxx>
With CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES enabled, archs can support 64bit
process invoke 32bit syscall via compatible mmap(), which uses
mmap_compat_base and mmap_compat_legacy_base of mm_struct, which only
x86 uses so far.
Here we assume other archs will support CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES
as well.
Signed-off-by: Xiongwei Song <sxwjean@xxxxxxxxx>
---
arch/x86/include/asm/processor.h | 4 ++++
mm/util.c | 21 +++++++++++++++++++--
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 577f342dbfb2..fb7a4f21d412 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -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 */
diff --git a/mm/util.c b/mm/util.c
index 38326ef21a3b..ab3711c445e6 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -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)
--
2.30.2