Re: [PATCH v4 04/14] arm64, mm: Move generic mmap layout functions to mm
On Sun, May 26, 2019 at 09:47:36AM -0400, Alexandre Ghiti wrote: > arm64 handles top-down mmap layout in a way that can be easily reused > by other architectures, so make it available in mm. > It then introduces a new config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT > that can be set by other architectures to benefit from those functions. > Note that this new config depends on MMU being enabled, if selected > without MMU support, a warning will be thrown. > > Suggested-by: Christoph Hellwig > Signed-off-by: Alexandre Ghiti > Reviewed-by: Christoph Hellwig Acked-by: Catalin Marinas
Re: [PATCH v4 04/14] arm64, mm: Move generic mmap layout functions to mm
On Sun, May 26, 2019 at 09:47:36AM -0400, Alexandre Ghiti wrote: > arm64 handles top-down mmap layout in a way that can be easily reused > by other architectures, so make it available in mm. > It then introduces a new config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT > that can be set by other architectures to benefit from those functions. > Note that this new config depends on MMU being enabled, if selected > without MMU support, a warning will be thrown. > > Suggested-by: Christoph Hellwig > Signed-off-by: Alexandre Ghiti > Reviewed-by: Christoph Hellwig Acked-by: Kees Cook -Kees > --- > arch/Kconfig | 10 > arch/arm64/Kconfig | 1 + > arch/arm64/include/asm/processor.h | 2 - > arch/arm64/mm/mmap.c | 76 - > kernel/sysctl.c| 6 ++- > mm/util.c | 78 +- > 6 files changed, 92 insertions(+), 81 deletions(-) > > diff --git a/arch/Kconfig b/arch/Kconfig > index c47b328eada0..df3ab04270fa 100644 > --- a/arch/Kconfig > +++ b/arch/Kconfig > @@ -701,6 +701,16 @@ config HAVE_ARCH_COMPAT_MMAP_BASES > and vice-versa 32-bit applications to call 64-bit mmap(). > Required for applications doing different bitness syscalls. > > +# This allows to use a set of generic functions to determine mmap base > +# address by giving priority to top-down scheme only if the process > +# is not in legacy mode (compat task, unlimited stack size or > +# sysctl_legacy_va_layout). > +# Architecture that selects this option can provide its own version of: > +# - STACK_RND_MASK > +config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT > + bool > + depends on MMU > + > config HAVE_COPY_THREAD_TLS > bool > help > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > index 4780eb7af842..3d754c19c11e 100644 > --- a/arch/arm64/Kconfig > +++ b/arch/arm64/Kconfig > @@ -69,6 +69,7 @@ config ARM64 > select ARCH_SUPPORTS_INT128 if GCC_VERSION >= 5 || CC_IS_CLANG > select ARCH_SUPPORTS_NUMA_BALANCING > select ARCH_WANT_COMPAT_IPC_PARSE_VERSION > + select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT > select ARCH_WANT_FRAME_POINTERS > select ARCH_HAS_UBSAN_SANITIZE_ALL > select ARM_AMBA > diff --git a/arch/arm64/include/asm/processor.h > b/arch/arm64/include/asm/processor.h > index fcd0e691b1ea..3bd818edf319 100644 > --- a/arch/arm64/include/asm/processor.h > +++ b/arch/arm64/include/asm/processor.h > @@ -282,8 +282,6 @@ static inline void spin_lock_prefetch(const void *ptr) >"nop") : : "p" (ptr)); > } > > -#define HAVE_ARCH_PICK_MMAP_LAYOUT > - > #endif > > extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */ > diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c > index ac89686c4af8..c74224421216 100644 > --- a/arch/arm64/mm/mmap.c > +++ b/arch/arm64/mm/mmap.c > @@ -31,82 +31,6 @@ > > #include > > -/* > - * Leave enough space between the mmap area and the stack to honour ulimit in > - * the face of randomisation. > - */ > -#define MIN_GAP (SZ_128M) > -#define MAX_GAP (STACK_TOP/6*5) > - > -static int mmap_is_legacy(struct rlimit *rlim_stack) > -{ > - if (current->personality & ADDR_COMPAT_LAYOUT) > - return 1; > - > - if (rlim_stack->rlim_cur == RLIM_INFINITY) > - return 1; > - > - return sysctl_legacy_va_layout; > -} > - > -unsigned long arch_mmap_rnd(void) > -{ > - unsigned long rnd; > - > -#ifdef CONFIG_COMPAT > - if (is_compat_task()) > - rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1); > - else > -#endif > - rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); > - return rnd << PAGE_SHIFT; > -} > - > -static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) > -{ > - unsigned long gap = rlim_stack->rlim_cur; > - unsigned long pad = stack_guard_gap; > - > - /* Account for stack randomization if necessary */ > - if (current->flags & PF_RANDOMIZE) > - pad += (STACK_RND_MASK << PAGE_SHIFT); > - > - /* Values close to RLIM_INFINITY can overflow. */ > - if (gap + pad > gap) > - gap += pad; > - > - if (gap < MIN_GAP) > - gap = MIN_GAP; > - else if (gap > MAX_GAP) > - gap = MAX_GAP; > - > - return PAGE_ALIGN(STACK_TOP - gap - rnd); > -} > - > -/* > - * This function, called very early during the creation of a new process VM > - * image, sets up which VM layout function to use: > - */ > -void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) > -{ > - unsigned long random_factor = 0UL; > - > - if (current->flags & PF_RANDOMIZE) > - random_factor = arch_mmap_rnd(); > - > - /* > - * Fall back to the standard layout if the personality bit is set, or > - * if the expected stack growth is unlimited: > - */ > -
[PATCH v4 04/14] arm64, mm: Move generic mmap layout functions to mm
arm64 handles top-down mmap layout in a way that can be easily reused by other architectures, so make it available in mm. It then introduces a new config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT that can be set by other architectures to benefit from those functions. Note that this new config depends on MMU being enabled, if selected without MMU support, a warning will be thrown. Suggested-by: Christoph Hellwig Signed-off-by: Alexandre Ghiti Reviewed-by: Christoph Hellwig --- arch/Kconfig | 10 arch/arm64/Kconfig | 1 + arch/arm64/include/asm/processor.h | 2 - arch/arm64/mm/mmap.c | 76 - kernel/sysctl.c| 6 ++- mm/util.c | 78 +- 6 files changed, 92 insertions(+), 81 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index c47b328eada0..df3ab04270fa 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -701,6 +701,16 @@ config HAVE_ARCH_COMPAT_MMAP_BASES and vice-versa 32-bit applications to call 64-bit mmap(). Required for applications doing different bitness syscalls. +# This allows to use a set of generic functions to determine mmap base +# address by giving priority to top-down scheme only if the process +# is not in legacy mode (compat task, unlimited stack size or +# sysctl_legacy_va_layout). +# Architecture that selects this option can provide its own version of: +# - STACK_RND_MASK +config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT + bool + depends on MMU + config HAVE_COPY_THREAD_TLS bool help diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 4780eb7af842..3d754c19c11e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -69,6 +69,7 @@ config ARM64 select ARCH_SUPPORTS_INT128 if GCC_VERSION >= 5 || CC_IS_CLANG select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_WANT_COMPAT_IPC_PARSE_VERSION + select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT select ARCH_WANT_FRAME_POINTERS select ARCH_HAS_UBSAN_SANITIZE_ALL select ARM_AMBA diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index fcd0e691b1ea..3bd818edf319 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -282,8 +282,6 @@ static inline void spin_lock_prefetch(const void *ptr) "nop") : : "p" (ptr)); } -#define HAVE_ARCH_PICK_MMAP_LAYOUT - #endif extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */ diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c index ac89686c4af8..c74224421216 100644 --- a/arch/arm64/mm/mmap.c +++ b/arch/arm64/mm/mmap.c @@ -31,82 +31,6 @@ #include -/* - * Leave enough space between the mmap area and the stack to honour ulimit in - * the face of randomisation. - */ -#define MIN_GAP (SZ_128M) -#define MAX_GAP(STACK_TOP/6*5) - -static int mmap_is_legacy(struct rlimit *rlim_stack) -{ - if (current->personality & ADDR_COMPAT_LAYOUT) - return 1; - - if (rlim_stack->rlim_cur == RLIM_INFINITY) - return 1; - - return sysctl_legacy_va_layout; -} - -unsigned long arch_mmap_rnd(void) -{ - unsigned long rnd; - -#ifdef CONFIG_COMPAT - if (is_compat_task()) - rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1); - else -#endif - rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); - return rnd << PAGE_SHIFT; -} - -static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) -{ - unsigned long gap = rlim_stack->rlim_cur; - unsigned long pad = stack_guard_gap; - - /* Account for stack randomization if necessary */ - if (current->flags & PF_RANDOMIZE) - pad += (STACK_RND_MASK << PAGE_SHIFT); - - /* Values close to RLIM_INFINITY can overflow. */ - if (gap + pad > gap) - gap += pad; - - if (gap < MIN_GAP) - gap = MIN_GAP; - else if (gap > MAX_GAP) - gap = MAX_GAP; - - return PAGE_ALIGN(STACK_TOP - gap - rnd); -} - -/* - * This function, called very early during the creation of a new process VM - * image, sets up which VM layout function to use: - */ -void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) -{ - unsigned long random_factor = 0UL; - - if (current->flags & PF_RANDOMIZE) - random_factor = arch_mmap_rnd(); - - /* -* Fall back to the standard layout if the personality bit is set, or -* if the expected stack growth is unlimited: -*/ - if (mmap_is_legacy(rlim_stack)) { - mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; - mm->get_unmapped_area = arch_get_unmapped_area; - } else { - mm->mmap_base = mmap_base(random_factor, rlim_stack); -