1 /* 2 * flexible mmap layout support 3 * 4 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 5 * All Rights Reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * 22 * Started by Ingo Molnar <mingo@elte.hu> 23 */ 24 25 #include <linux/elf-randomize.h> 26 #include <linux/personality.h> 27 #include <linux/mm.h> 28 #include <linux/mman.h> 29 #include <linux/sched/signal.h> 30 #include <linux/sched/mm.h> 31 #include <linux/random.h> 32 #include <linux/compat.h> 33 #include <linux/security.h> 34 #include <asm/pgalloc.h> 35 #include <asm/elf.h> 36 37 static unsigned long stack_maxrandom_size(void) 38 { 39 if (!(current->flags & PF_RANDOMIZE)) 40 return 0; 41 if (current->personality & ADDR_NO_RANDOMIZE) 42 return 0; 43 return STACK_RND_MASK << PAGE_SHIFT; 44 } 45 46 /* 47 * Top of mmap area (just below the process stack). 48 * 49 * Leave at least a ~32 MB hole. 50 */ 51 #define MIN_GAP (32*1024*1024) 52 #define MAX_GAP (STACK_TOP/6*5) 53 54 static inline int mmap_is_legacy(void) 55 { 56 if (current->personality & ADDR_COMPAT_LAYOUT) 57 return 1; 58 if (rlimit(RLIMIT_STACK) == RLIM_INFINITY) 59 return 1; 60 return sysctl_legacy_va_layout; 61 } 62 63 unsigned long arch_mmap_rnd(void) 64 { 65 return (get_random_int() & MMAP_RND_MASK) << PAGE_SHIFT; 66 } 67 68 static unsigned long mmap_base_legacy(unsigned long rnd) 69 { 70 return TASK_UNMAPPED_BASE + rnd; 71 } 72 73 static inline unsigned long mmap_base(unsigned long rnd) 74 { 75 unsigned long gap = rlimit(RLIMIT_STACK); 76 77 if (gap < MIN_GAP) 78 gap = MIN_GAP; 79 else if (gap > MAX_GAP) 80 gap = MAX_GAP; 81 gap &= PAGE_MASK; 82 return STACK_TOP - stack_maxrandom_size() - rnd - gap; 83 } 84 85 unsigned long 86 arch_get_unmapped_area(struct file *filp, unsigned long addr, 87 unsigned long len, unsigned long pgoff, unsigned long flags) 88 { 89 struct mm_struct *mm = current->mm; 90 struct vm_area_struct *vma; 91 struct vm_unmapped_area_info info; 92 int rc; 93 94 if (len > TASK_SIZE - mmap_min_addr) 95 return -ENOMEM; 96 97 if (flags & MAP_FIXED) 98 goto check_asce_limit; 99 100 if (addr) { 101 addr = PAGE_ALIGN(addr); 102 vma = find_vma(mm, addr); 103 if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && 104 (!vma || addr + len <= vma->vm_start)) 105 goto check_asce_limit; 106 } 107 108 info.flags = 0; 109 info.length = len; 110 info.low_limit = mm->mmap_base; 111 info.high_limit = TASK_SIZE; 112 if (filp || (flags & MAP_SHARED)) 113 info.align_mask = MMAP_ALIGN_MASK << PAGE_SHIFT; 114 else 115 info.align_mask = 0; 116 info.align_offset = pgoff << PAGE_SHIFT; 117 addr = vm_unmapped_area(&info); 118 if (addr & ~PAGE_MASK) 119 return addr; 120 121 check_asce_limit: 122 if (addr + len > current->mm->context.asce_limit) { 123 rc = crst_table_upgrade(mm); 124 if (rc) 125 return (unsigned long) rc; 126 } 127 128 return addr; 129 } 130 131 unsigned long 132 arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, 133 const unsigned long len, const unsigned long pgoff, 134 const unsigned long flags) 135 { 136 struct vm_area_struct *vma; 137 struct mm_struct *mm = current->mm; 138 unsigned long addr = addr0; 139 struct vm_unmapped_area_info info; 140 int rc; 141 142 /* requested length too big for entire address space */ 143 if (len > TASK_SIZE - mmap_min_addr) 144 return -ENOMEM; 145 146 if (flags & MAP_FIXED) 147 goto check_asce_limit; 148 149 /* requesting a specific address */ 150 if (addr) { 151 addr = PAGE_ALIGN(addr); 152 vma = find_vma(mm, addr); 153 if (TASK_SIZE - len >= addr && addr >= mmap_min_addr && 154 (!vma || addr + len <= vma->vm_start)) 155 goto check_asce_limit; 156 } 157 158 info.flags = VM_UNMAPPED_AREA_TOPDOWN; 159 info.length = len; 160 info.low_limit = max(PAGE_SIZE, mmap_min_addr); 161 info.high_limit = mm->mmap_base; 162 if (filp || (flags & MAP_SHARED)) 163 info.align_mask = MMAP_ALIGN_MASK << PAGE_SHIFT; 164 else 165 info.align_mask = 0; 166 info.align_offset = pgoff << PAGE_SHIFT; 167 addr = vm_unmapped_area(&info); 168 169 /* 170 * A failed mmap() very likely causes application failure, 171 * so fall back to the bottom-up function here. This scenario 172 * can happen with large stack limits and large mmap() 173 * allocations. 174 */ 175 if (addr & ~PAGE_MASK) { 176 VM_BUG_ON(addr != -ENOMEM); 177 info.flags = 0; 178 info.low_limit = TASK_UNMAPPED_BASE; 179 info.high_limit = TASK_SIZE; 180 addr = vm_unmapped_area(&info); 181 if (addr & ~PAGE_MASK) 182 return addr; 183 } 184 185 check_asce_limit: 186 if (addr + len > current->mm->context.asce_limit) { 187 rc = crst_table_upgrade(mm); 188 if (rc) 189 return (unsigned long) rc; 190 } 191 192 return addr; 193 } 194 195 /* 196 * This function, called very early during the creation of a new 197 * process VM image, sets up which VM layout function to use: 198 */ 199 void arch_pick_mmap_layout(struct mm_struct *mm) 200 { 201 unsigned long random_factor = 0UL; 202 203 if (current->flags & PF_RANDOMIZE) 204 random_factor = arch_mmap_rnd(); 205 206 /* 207 * Fall back to the standard layout if the personality 208 * bit is set, or if the expected stack growth is unlimited: 209 */ 210 if (mmap_is_legacy()) { 211 mm->mmap_base = mmap_base_legacy(random_factor); 212 mm->get_unmapped_area = arch_get_unmapped_area; 213 } else { 214 mm->mmap_base = mmap_base(random_factor); 215 mm->get_unmapped_area = arch_get_unmapped_area_topdown; 216 } 217 } 218