[RESEND PATCH v4 5/8] arm64: mm: Use HAVE_ARCH_COMPAT_MMAP_BASES

Amanieu d'Antras
2021-05-18T09:08:06Z

This patch switches arm64 to use separate mmap_base for 32-bit and
64-bit mmaps. This is needed to ensure that compat syscalls
invoked by 64-bit tasks perform VM allocations in the low 4G of the
address space.

Signed-off-by: Amanieu d'Antras <amanieu@gmail.com>
Co-developed-by: Ryan Houdek <Houdek.Ryan@fex-emu.org>
Signed-off-by: Ryan Houdek <Houdek.Ryan@fex-emu.org>
---
arch/arm64/Kconfig | 1 +
arch/arm64/include/asm/elf.h | 8 +++++---
arch/arm64/include/asm/processor.h | 33 ++++++++++++++++++------------
arch/arm64/mm/mmap.c | 33 ++++++++++++++++++++++++++++++
4 files changed, 59 insertions(+), 16 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index dfdc3e0af5e1..d57b7bcbd758 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -133,6 +133,7 @@ config ARM64
select HAVE_ALIGNED_STRUCT_PAGE if SLUB
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_BITREVERSE
+ select HAVE_ARCH_COMPAT_MMAP_BASES if COMPAT
select HAVE_ARCH_COMPILER_H
select HAVE_ARCH_HUGE_VMAP
select HAVE_ARCH_JUMP_LABEL
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 8d1c8dcb87fd..e21964898d06 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -187,12 +187,14 @@ extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int uses_interp);

/* 1GB of VA */
+#define STACK_RND_MASK_64 (0x3ffff >> (PAGE_SHIFT - 12))
#ifdef CONFIG_COMPAT
+#define STACK_RND_MASK_32 (0x7ff >> (PAGE_SHIFT - 12))
#define STACK_RND_MASK (test_thread_flag(TIF_32BIT) ? \
- 0x7ff >> (PAGE_SHIFT - 12) : \
- 0x3ffff >> (PAGE_SHIFT - 12))
+ STACK_RND_MASK_32 : \
+ STACK_RND_MASK_64)
#else
-#define STACK_RND_MASK (0x3ffff >> (PAGE_SHIFT - 12))
+#define STACK_RND_MASK STACK_RND_MASK_64
#endif

#ifdef __AARCH64EB__
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index f47528aae321..f8309f8d0ece 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -70,29 +70,36 @@

#ifdef CONFIG_ARM64_FORCE_52BIT
#define STACK_TOP_MAX TASK_SIZE_64
-#define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 4))
+#define TASK_UNMAPPED_BASE_64 (PAGE_ALIGN(TASK_SIZE_64 / 4))
#else
#define STACK_TOP_MAX DEFAULT_MAP_WINDOW_64
-#define TASK_UNMAPPED_BASE (PAGE_ALIGN(DEFAULT_MAP_WINDOW / 4))
+#define TASK_UNMAPPED_BASE_64 (PAGE_ALIGN(DEFAULT_MAP_WINDOW_64 / 4))
#endif /* CONFIG_ARM64_FORCE_52BIT */

+#ifdef CONFIG_COMPAT
+#define TASK_UNMAPPED_BASE_32 (PAGE_ALIGN(TASK_SIZE_32 / 4))
+#define TASK_UNMAPPED_BASE (test_thread_flag(TIF_32BIT) ? \
+ TASK_UNMAPPED_BASE_32 : TASK_UNMAPPED_BASE_64)
+#else
+#define TASK_UNMAPPED_BASE TASK_UNMAPPED_BASE_64
+#endif /* CONFIG_COMPAT */
+
+#define STACK_TOP_64 STACK_TOP_MAX
#ifdef CONFIG_COMPAT
#define AARCH32_VECTORS_BASE 0xffff0000
+#define STACK_TOP_32 AARCH32_VECTORS_BASE
#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
- AARCH32_VECTORS_BASE : STACK_TOP_MAX)
+ STACK_TOP_32 : STACK_TOP_64)
#else
-#define STACK_TOP STACK_TOP_MAX
+#define STACK_TOP STACK_TOP_64
#endif /* CONFIG_COMPAT */

-#ifndef CONFIG_ARM64_FORCE_52BIT
-#define arch_get_mmap_end(addr) ((addr > DEFAULT_MAP_WINDOW) ? TASK_SIZE :\
- DEFAULT_MAP_WINDOW)
-
-#define arch_get_mmap_base_topdown(addr) \
- ((addr > DEFAULT_MAP_WINDOW) ? \
- current->mm->mmap_base + TASK_SIZE - DEFAULT_MAP_WINDOW :\
- current->mm->mmap_base)
-#endif /* CONFIG_ARM64_FORCE_52BIT */
+#define arch_get_mmap_end arch_get_mmap_end
+#define arch_get_mmap_base arch_get_mmap_base
+#define arch_get_mmap_base_topdown arch_get_mmap_base_topdown
+unsigned long arch_get_mmap_end(unsigned long addr);
+unsigned long arch_get_mmap_base(unsigned long addr);
+unsigned long arch_get_mmap_base_topdown(unsigned long addr);

extern phys_addr_t arm64_dma_phys_limit;
#define ARCH_LOW_ADDRESS_LIMIT (arm64_dma_phys_limit - 1)
diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c
index a38f54cd638c..956cab3ade11 100644
--- a/arch/arm64/mm/mmap.c
+++ b/arch/arm64/mm/mmap.c
@@ -38,3 +38,36 @@ int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
{
return !(((pfn << PAGE_SHIFT) + size) & ~PHYS_MASK);
}
+
+unsigned long arch_get_mmap_end(unsigned long addr)
+{
+#ifdef CONFIG_COMPAT
+ if (in_compat_syscall())
+ return TASK_SIZE_32;
+#endif /* CONFIG_COMPAT */
+#ifndef CONFIG_ARM64_FORCE_52BIT
+ if (addr > DEFAULT_MAP_WINDOW_64)
+ return TASK_SIZE_64;
+#endif /* CONFIG_ARM64_FORCE_52BIT */
+ return DEFAULT_MAP_WINDOW_64;
+}
+unsigned long arch_get_mmap_base(unsigned long addr)
+{
+#ifdef CONFIG_COMPAT
+ if (in_compat_syscall())
+ return current->mm->mmap_compat_base;
+#endif /* CONFIG_COMPAT */
+ return current->mm->mmap_base;
+}
+unsigned long arch_get_mmap_base_topdown(unsigned long addr)
+{
+#ifdef CONFIG_COMPAT
+ if (in_compat_syscall())
+ return current->mm->mmap_compat_base;
+#endif /* CONFIG_COMPAT */
+#ifndef CONFIG_ARM64_FORCE_52BIT
+ if (addr > DEFAULT_MAP_WINDOW_64)
+ return current->mm->mmap_base + TASK_SIZE - DEFAULT_MAP_WINDOW_64;
+#endif /* CONFIG_ARM64_FORCE_52BIT */
+ return current->mm->mmap_base;
+}
--
2.31.1