Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mips: use generic mmap top-down layout and brk randomization

mips uses a top-down layout by default that exactly fits the generic
functions, so get rid of arch specific code and use the generic version by
selecting ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT.

As ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT selects ARCH_HAS_ELF_RANDOMIZE,
use the generic version of arch_randomize_brk since it also fits. Note
that this commit also removes the possibility for mips to have elf
randomization and no MMU: without MMU, the security added by randomization
is worth nothing.

Link: http://lkml.kernel.org/r/20190730055113.23635-14-alex@ghiti.fr
Signed-off-by: Alexandre Ghiti <alex@ghiti.fr>
Acked-by: Paul Burton <paul.burton@mips.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: James Hogan <jhogan@kernel.org>
Cc: Palmer Dabbelt <palmer@sifive.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Alexandre Ghiti and committed by
Linus Torvalds
9035bd29 09036468

+1 -102
+1 -1
arch/mips/Kconfig
··· 5 5 select ARCH_32BIT_OFF_T if !64BIT 6 6 select ARCH_BINFMT_ELF_STATE if MIPS_FP_SUPPORT 7 7 select ARCH_CLOCKSOURCE_DATA 8 - select ARCH_HAS_ELF_RANDOMIZE 9 8 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST 10 9 select ARCH_HAS_UBSAN_SANITIZE_ALL 11 10 select ARCH_SUPPORTS_UPROBES ··· 12 13 select ARCH_USE_CMPXCHG_LOCKREF if 64BIT 13 14 select ARCH_USE_QUEUED_RWLOCKS 14 15 select ARCH_USE_QUEUED_SPINLOCKS 16 + select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU 15 17 select ARCH_WANT_IPC_PARSE_VERSION 16 18 select BUILDTIME_EXTABLE_SORT 17 19 select CLONE_BACKWARDS
-5
arch/mips/include/asm/processor.h
··· 29 29 30 30 extern unsigned int vced_count, vcei_count; 31 31 32 - /* 33 - * MIPS does have an arch_pick_mmap_layout() 34 - */ 35 - #define HAVE_ARCH_PICK_MMAP_LAYOUT 1 36 - 37 32 #ifdef CONFIG_32BIT 38 33 #ifdef CONFIG_KVM_GUEST 39 34 /* User space process size is limited to 1GB in KVM Guest Mode */
-96
arch/mips/mm/mmap.c
··· 16 16 #include <linux/random.h> 17 17 #include <linux/sched/signal.h> 18 18 #include <linux/sched/mm.h> 19 - #include <linux/sizes.h> 20 - #include <linux/compat.h> 21 19 22 20 unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ 23 21 EXPORT_SYMBOL(shm_align_mask); 24 - 25 - /* gap between mmap and stack */ 26 - #define MIN_GAP (128*1024*1024UL) 27 - #define MAX_GAP ((STACK_TOP)/6*5) 28 - #define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12)) 29 - 30 - static int mmap_is_legacy(struct rlimit *rlim_stack) 31 - { 32 - if (current->personality & ADDR_COMPAT_LAYOUT) 33 - return 1; 34 - 35 - if (rlim_stack->rlim_cur == RLIM_INFINITY) 36 - return 1; 37 - 38 - return sysctl_legacy_va_layout; 39 - } 40 - 41 - static unsigned long mmap_base(unsigned long rnd, struct rlimit *rlim_stack) 42 - { 43 - unsigned long gap = rlim_stack->rlim_cur; 44 - unsigned long pad = stack_guard_gap; 45 - 46 - /* Account for stack randomization if necessary */ 47 - if (current->flags & PF_RANDOMIZE) 48 - pad += (STACK_RND_MASK << PAGE_SHIFT); 49 - 50 - /* Values close to RLIM_INFINITY can overflow. */ 51 - if (gap + pad > gap) 52 - gap += pad; 53 - 54 - if (gap < MIN_GAP) 55 - gap = MIN_GAP; 56 - else if (gap > MAX_GAP) 57 - gap = MAX_GAP; 58 - 59 - return PAGE_ALIGN(STACK_TOP - gap - rnd); 60 - } 61 22 62 23 #define COLOUR_ALIGN(addr, pgoff) \ 63 24 ((((addr) + shm_align_mask) & ~shm_align_mask) + \ ··· 115 154 { 116 155 return arch_get_unmapped_area_common(filp, 117 156 addr0, len, pgoff, flags, DOWN); 118 - } 119 - 120 - unsigned long arch_mmap_rnd(void) 121 - { 122 - unsigned long rnd; 123 - 124 - #ifdef CONFIG_COMPAT 125 - if (TASK_IS_32BIT_ADDR) 126 - rnd = get_random_long() & ((1UL << mmap_rnd_compat_bits) - 1); 127 - else 128 - #endif /* CONFIG_COMPAT */ 129 - rnd = get_random_long() & ((1UL << mmap_rnd_bits) - 1); 130 - 131 - return rnd << PAGE_SHIFT; 132 - } 133 - 134 - void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) 135 - { 136 - unsigned long random_factor = 0UL; 137 - 138 - if (current->flags & PF_RANDOMIZE) 139 - random_factor = arch_mmap_rnd(); 140 - 141 - if (mmap_is_legacy(rlim_stack)) { 142 - mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; 143 - mm->get_unmapped_area = arch_get_unmapped_area; 144 - } else { 145 - mm->mmap_base = mmap_base(random_factor, rlim_stack); 146 - mm->get_unmapped_area = arch_get_unmapped_area_topdown; 147 - } 148 - } 149 - 150 - static inline unsigned long brk_rnd(void) 151 - { 152 - unsigned long rnd = get_random_long(); 153 - 154 - rnd = rnd << PAGE_SHIFT; 155 - /* 32MB for 32bit, 1GB for 64bit */ 156 - if (!IS_ENABLED(CONFIG_64BIT) || is_compat_task()) 157 - rnd = rnd & (SZ_32M - 1); 158 - else 159 - rnd = rnd & (SZ_1G - 1); 160 - 161 - return rnd; 162 - } 163 - 164 - unsigned long arch_randomize_brk(struct mm_struct *mm) 165 - { 166 - unsigned long base = mm->brk; 167 - unsigned long ret; 168 - 169 - ret = PAGE_ALIGN(base + brk_rnd()); 170 - 171 - if (ret < mm->brk) 172 - return mm->brk; 173 - 174 - return ret; 175 157 } 176 158 177 159 bool __virt_addr_valid(const volatile void *kaddr)