1675a0813SHarvey Harrison /* 2675a0813SHarvey Harrison * Flexible mmap layout support 3675a0813SHarvey Harrison * 4675a0813SHarvey Harrison * Based on code by Ingo Molnar and Andi Kleen, copyrighted 5675a0813SHarvey Harrison * as follows: 6675a0813SHarvey Harrison * 78f47e163SIngo Molnar * Copyright 2003-2009 Red Hat Inc. 8675a0813SHarvey Harrison * All Rights Reserved. 9675a0813SHarvey Harrison * Copyright 2005 Andi Kleen, SUSE Labs. 10675a0813SHarvey Harrison * Copyright 2007 Jiri Kosina, SUSE Labs. 11675a0813SHarvey Harrison * 12675a0813SHarvey Harrison * This program is free software; you can redistribute it and/or modify 13675a0813SHarvey Harrison * it under the terms of the GNU General Public License as published by 14675a0813SHarvey Harrison * the Free Software Foundation; either version 2 of the License, or 15675a0813SHarvey Harrison * (at your option) any later version. 16675a0813SHarvey Harrison * 17675a0813SHarvey Harrison * This program is distributed in the hope that it will be useful, 18675a0813SHarvey Harrison * but WITHOUT ANY WARRANTY; without even the implied warranty of 19675a0813SHarvey Harrison * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20675a0813SHarvey Harrison * GNU General Public License for more details. 21675a0813SHarvey Harrison * 22675a0813SHarvey Harrison * You should have received a copy of the GNU General Public License 23675a0813SHarvey Harrison * along with this program; if not, write to the Free Software 24675a0813SHarvey Harrison * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25675a0813SHarvey Harrison */ 26675a0813SHarvey Harrison 27675a0813SHarvey Harrison #include <linux/personality.h> 28675a0813SHarvey Harrison #include <linux/mm.h> 29675a0813SHarvey Harrison #include <linux/random.h> 30675a0813SHarvey Harrison #include <linux/limits.h> 313f07c014SIngo Molnar #include <linux/sched/signal.h> 3201042607SIngo Molnar #include <linux/sched/mm.h> 33e13b73ddSDmitry Safonov #include <linux/compat.h> 3480938332SMichal Hocko #include <asm/elf.h> 3580938332SMichal Hocko 36be62a320SCraig Bergstrom #include "physaddr.h" 37be62a320SCraig Bergstrom 38cc99535eSJan-Simon Möller struct va_alignment __read_mostly va_align = { 399387f774SBorislav Petkov .flags = -1, 409387f774SBorislav Petkov }; 419387f774SBorislav Petkov 42e8f01a8dSKirill A. Shutemov unsigned long task_size_32bit(void) 438f3e474fSDmitry Safonov { 448f3e474fSDmitry Safonov return IA32_PAGE_OFFSET; 458f3e474fSDmitry Safonov } 468f3e474fSDmitry Safonov 47b569bab7SKirill A. Shutemov unsigned long task_size_64bit(int full_addr_space) 481b028f78SDmitry Safonov { 49b569bab7SKirill A. Shutemov return full_addr_space ? TASK_SIZE_MAX : DEFAULT_MAP_WINDOW; 501b028f78SDmitry Safonov } 511b028f78SDmitry Safonov 528f3e474fSDmitry Safonov static unsigned long stack_maxrandom_size(unsigned long task_size) 5380938332SMichal Hocko { 544e7c22d4SHector Marco-Gisbert unsigned long max = 0; 5501578e36SOleg Nesterov if (current->flags & PF_RANDOMIZE) { 56e8f01a8dSKirill A. Shutemov max = (-1UL) & __STACK_RND_MASK(task_size == task_size_32bit()); 578f3e474fSDmitry Safonov max <<= PAGE_SHIFT; 5880938332SMichal Hocko } 5980938332SMichal Hocko 6080938332SMichal Hocko return max; 6180938332SMichal Hocko } 6280938332SMichal Hocko 636a0b41d1SDmitry Safonov #ifdef CONFIG_COMPAT 646a0b41d1SDmitry Safonov # define mmap32_rnd_bits mmap_rnd_compat_bits 656a0b41d1SDmitry Safonov # define mmap64_rnd_bits mmap_rnd_bits 666a0b41d1SDmitry Safonov #else 676a0b41d1SDmitry Safonov # define mmap32_rnd_bits mmap_rnd_bits 686a0b41d1SDmitry Safonov # define mmap64_rnd_bits mmap_rnd_bits 696a0b41d1SDmitry Safonov #endif 706a0b41d1SDmitry Safonov 718f3e474fSDmitry Safonov #define SIZE_128M (128 * 1024 * 1024UL) 728f3e474fSDmitry Safonov 73675a0813SHarvey Harrison static int mmap_is_legacy(void) 74675a0813SHarvey Harrison { 75675a0813SHarvey Harrison if (current->personality & ADDR_COMPAT_LAYOUT) 76675a0813SHarvey Harrison return 1; 77675a0813SHarvey Harrison 78675a0813SHarvey Harrison return sysctl_legacy_va_layout; 79675a0813SHarvey Harrison } 80675a0813SHarvey Harrison 816a0b41d1SDmitry Safonov static unsigned long arch_rnd(unsigned int rndbits) 826a0b41d1SDmitry Safonov { 8347ac5484SOleg Nesterov if (!(current->flags & PF_RANDOMIZE)) 8447ac5484SOleg Nesterov return 0; 856a0b41d1SDmitry Safonov return (get_random_long() & ((1UL << rndbits) - 1)) << PAGE_SHIFT; 866a0b41d1SDmitry Safonov } 876a0b41d1SDmitry Safonov 882b68f6caSKees Cook unsigned long arch_mmap_rnd(void) 89675a0813SHarvey Harrison { 906a0b41d1SDmitry Safonov return arch_rnd(mmap_is_ia32() ? mmap32_rnd_bits : mmap64_rnd_bits); 91675a0813SHarvey Harrison } 92675a0813SHarvey Harrison 938f2af155SKees Cook static unsigned long mmap_base(unsigned long rnd, unsigned long task_size, 948f2af155SKees Cook struct rlimit *rlim_stack) 95675a0813SHarvey Harrison { 968f2af155SKees Cook unsigned long gap = rlim_stack->rlim_cur; 97c204d21fSRik van Riel unsigned long pad = stack_maxrandom_size(task_size) + stack_guard_gap; 988f3e474fSDmitry Safonov unsigned long gap_min, gap_max; 99675a0813SHarvey Harrison 100c204d21fSRik van Riel /* Values close to RLIM_INFINITY can overflow. */ 101c204d21fSRik van Riel if (gap + pad > gap) 102c204d21fSRik van Riel gap += pad; 103c204d21fSRik van Riel 1048f3e474fSDmitry Safonov /* 1058f3e474fSDmitry Safonov * Top of mmap area (just below the process stack). 1068f3e474fSDmitry Safonov * Leave an at least ~128 MB hole with possible stack randomization. 1078f3e474fSDmitry Safonov */ 108c204d21fSRik van Riel gap_min = SIZE_128M; 1098f3e474fSDmitry Safonov gap_max = (task_size / 6) * 5; 110675a0813SHarvey Harrison 1118f3e474fSDmitry Safonov if (gap < gap_min) 1128f3e474fSDmitry Safonov gap = gap_min; 1138f3e474fSDmitry Safonov else if (gap > gap_max) 1148f3e474fSDmitry Safonov gap = gap_max; 1158f3e474fSDmitry Safonov 1168f3e474fSDmitry Safonov return PAGE_ALIGN(task_size - gap - rnd); 1178f3e474fSDmitry Safonov } 1188f3e474fSDmitry Safonov 1198f3e474fSDmitry Safonov static unsigned long mmap_legacy_base(unsigned long rnd, 1208f3e474fSDmitry Safonov unsigned long task_size) 1218f3e474fSDmitry Safonov { 1228f3e474fSDmitry Safonov return __TASK_UNMAPPED_BASE(task_size) + rnd; 123675a0813SHarvey Harrison } 124675a0813SHarvey Harrison 125675a0813SHarvey Harrison /* 126675a0813SHarvey Harrison * This function, called very early during the creation of a new 127675a0813SHarvey Harrison * process VM image, sets up which VM layout function to use: 128675a0813SHarvey Harrison */ 1291b028f78SDmitry Safonov static void arch_pick_mmap_base(unsigned long *base, unsigned long *legacy_base, 1308f2af155SKees Cook unsigned long random_factor, unsigned long task_size, 1318f2af155SKees Cook struct rlimit *rlim_stack) 1321b028f78SDmitry Safonov { 1331b028f78SDmitry Safonov *legacy_base = mmap_legacy_base(random_factor, task_size); 1341b028f78SDmitry Safonov if (mmap_is_legacy()) 1351b028f78SDmitry Safonov *base = *legacy_base; 1361b028f78SDmitry Safonov else 1378f2af155SKees Cook *base = mmap_base(random_factor, task_size, rlim_stack); 1381b028f78SDmitry Safonov } 1391b028f78SDmitry Safonov 1408f2af155SKees Cook void arch_pick_mmap_layout(struct mm_struct *mm, struct rlimit *rlim_stack) 141675a0813SHarvey Harrison { 1421b028f78SDmitry Safonov if (mmap_is_legacy()) 143675a0813SHarvey Harrison mm->get_unmapped_area = arch_get_unmapped_area; 1441b028f78SDmitry Safonov else 145675a0813SHarvey Harrison mm->get_unmapped_area = arch_get_unmapped_area_topdown; 1461b028f78SDmitry Safonov 1471b028f78SDmitry Safonov arch_pick_mmap_base(&mm->mmap_base, &mm->mmap_legacy_base, 1488f2af155SKees Cook arch_rnd(mmap64_rnd_bits), task_size_64bit(0), 1498f2af155SKees Cook rlim_stack); 1501b028f78SDmitry Safonov 1511b028f78SDmitry Safonov #ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES 1521b028f78SDmitry Safonov /* 1531b028f78SDmitry Safonov * The mmap syscall mapping base decision depends solely on the 1541b028f78SDmitry Safonov * syscall type (64-bit or compat). This applies for 64bit 1551b028f78SDmitry Safonov * applications and 32bit applications. The 64bit syscall uses 1561b028f78SDmitry Safonov * mmap_base, the compat syscall uses mmap_compat_base. 1571b028f78SDmitry Safonov */ 1581b028f78SDmitry Safonov arch_pick_mmap_base(&mm->mmap_compat_base, &mm->mmap_compat_legacy_base, 1598f2af155SKees Cook arch_rnd(mmap32_rnd_bits), task_size_32bit(), 1608f2af155SKees Cook rlim_stack); 1611b028f78SDmitry Safonov #endif 162675a0813SHarvey Harrison } 163a8965276SKirill A. Shutemov 164e13b73ddSDmitry Safonov unsigned long get_mmap_base(int is_legacy) 165e13b73ddSDmitry Safonov { 166e13b73ddSDmitry Safonov struct mm_struct *mm = current->mm; 167e13b73ddSDmitry Safonov 168e13b73ddSDmitry Safonov #ifdef CONFIG_HAVE_ARCH_COMPAT_MMAP_BASES 169a846446bSDmitry Safonov if (in_32bit_syscall()) { 170e13b73ddSDmitry Safonov return is_legacy ? mm->mmap_compat_legacy_base 171e13b73ddSDmitry Safonov : mm->mmap_compat_base; 172e13b73ddSDmitry Safonov } 173e13b73ddSDmitry Safonov #endif 174e13b73ddSDmitry Safonov return is_legacy ? mm->mmap_legacy_base : mm->mmap_base; 175e13b73ddSDmitry Safonov } 176e13b73ddSDmitry Safonov 177a8965276SKirill A. Shutemov const char *arch_vma_name(struct vm_area_struct *vma) 178a8965276SKirill A. Shutemov { 179a8965276SKirill A. Shutemov if (vma->vm_flags & VM_MPX) 180a8965276SKirill A. Shutemov return "[mpx]"; 181a8965276SKirill A. Shutemov return NULL; 182a8965276SKirill A. Shutemov } 1831e0f25dbSKirill A. Shutemov 1841e0f25dbSKirill A. Shutemov /** 1851e0f25dbSKirill A. Shutemov * mmap_address_hint_valid - Validate the address hint of mmap 1861e0f25dbSKirill A. Shutemov * @addr: Address hint 1871e0f25dbSKirill A. Shutemov * @len: Mapping length 1881e0f25dbSKirill A. Shutemov * 1891e0f25dbSKirill A. Shutemov * Check whether @addr and @addr + @len result in a valid mapping. 1901e0f25dbSKirill A. Shutemov * 1911e0f25dbSKirill A. Shutemov * On 32bit this only checks whether @addr + @len is <= TASK_SIZE. 1921e0f25dbSKirill A. Shutemov * 1931e0f25dbSKirill A. Shutemov * On 64bit with 5-level page tables another sanity check is required 1941e0f25dbSKirill A. Shutemov * because mappings requested by mmap(@addr, 0) which cross the 47-bit 1951e0f25dbSKirill A. Shutemov * virtual address boundary can cause the following theoretical issue: 1961e0f25dbSKirill A. Shutemov * 1971e0f25dbSKirill A. Shutemov * An application calls mmap(addr, 0), i.e. without MAP_FIXED, where @addr 1981e0f25dbSKirill A. Shutemov * is below the border of the 47-bit address space and @addr + @len is 1991e0f25dbSKirill A. Shutemov * above the border. 2001e0f25dbSKirill A. Shutemov * 2011e0f25dbSKirill A. Shutemov * With 4-level paging this request succeeds, but the resulting mapping 2021e0f25dbSKirill A. Shutemov * address will always be within the 47-bit virtual address space, because 2031e0f25dbSKirill A. Shutemov * the hint address does not result in a valid mapping and is 2041e0f25dbSKirill A. Shutemov * ignored. Hence applications which are not prepared to handle virtual 2051e0f25dbSKirill A. Shutemov * addresses above 47-bit work correctly. 2061e0f25dbSKirill A. Shutemov * 2071e0f25dbSKirill A. Shutemov * With 5-level paging this request would be granted and result in a 2081e0f25dbSKirill A. Shutemov * mapping which crosses the border of the 47-bit virtual address 2091e0f25dbSKirill A. Shutemov * space. If the application cannot handle addresses above 47-bit this 2101e0f25dbSKirill A. Shutemov * will lead to misbehaviour and hard to diagnose failures. 2111e0f25dbSKirill A. Shutemov * 2121e0f25dbSKirill A. Shutemov * Therefore ignore address hints which would result in a mapping crossing 2131e0f25dbSKirill A. Shutemov * the 47-bit virtual address boundary. 2141e0f25dbSKirill A. Shutemov * 2151e0f25dbSKirill A. Shutemov * Note, that in the same scenario with MAP_FIXED the behaviour is 2161e0f25dbSKirill A. Shutemov * different. The request with @addr < 47-bit and @addr + @len > 47-bit 2171e0f25dbSKirill A. Shutemov * fails on a 4-level paging machine but succeeds on a 5-level paging 2181e0f25dbSKirill A. Shutemov * machine. It is reasonable to expect that an application does not rely on 2191e0f25dbSKirill A. Shutemov * the failure of such a fixed mapping request, so the restriction is not 2201e0f25dbSKirill A. Shutemov * applied. 2211e0f25dbSKirill A. Shutemov */ 2221e0f25dbSKirill A. Shutemov bool mmap_address_hint_valid(unsigned long addr, unsigned long len) 2231e0f25dbSKirill A. Shutemov { 2241e0f25dbSKirill A. Shutemov if (TASK_SIZE - len < addr) 2251e0f25dbSKirill A. Shutemov return false; 2261e0f25dbSKirill A. Shutemov 2271e0f25dbSKirill A. Shutemov return (addr > DEFAULT_MAP_WINDOW) == (addr + len > DEFAULT_MAP_WINDOW); 2281e0f25dbSKirill A. Shutemov } 229be62a320SCraig Bergstrom 230be62a320SCraig Bergstrom /* Can we access it for direct reading/writing? Must be RAM: */ 231be62a320SCraig Bergstrom int valid_phys_addr_range(phys_addr_t addr, size_t count) 232be62a320SCraig Bergstrom { 233*92c77f7cSRalph Campbell return addr + count - 1 <= __pa(high_memory - 1); 234be62a320SCraig Bergstrom } 235be62a320SCraig Bergstrom 236be62a320SCraig Bergstrom /* Can we access it through mmap? Must be a valid physical address: */ 237be62a320SCraig Bergstrom int valid_mmap_phys_addr_range(unsigned long pfn, size_t count) 238be62a320SCraig Bergstrom { 239be62a320SCraig Bergstrom phys_addr_t addr = (phys_addr_t)pfn << PAGE_SHIFT; 240be62a320SCraig Bergstrom 241be62a320SCraig Bergstrom return phys_addr_valid(addr + count - 1); 242be62a320SCraig Bergstrom } 24342e4089cSAndi Kleen 24442e4089cSAndi Kleen /* 24542e4089cSAndi Kleen * Only allow root to set high MMIO mappings to PROT_NONE. 24642e4089cSAndi Kleen * This prevents an unpriv. user to set them to PROT_NONE and invert 24742e4089cSAndi Kleen * them, then pointing to valid memory for L1TF speculation. 24842e4089cSAndi Kleen * 24942e4089cSAndi Kleen * Note: for locked down kernels may want to disable the root override. 25042e4089cSAndi Kleen */ 25142e4089cSAndi Kleen bool pfn_modify_allowed(unsigned long pfn, pgprot_t prot) 25242e4089cSAndi Kleen { 25342e4089cSAndi Kleen if (!boot_cpu_has_bug(X86_BUG_L1TF)) 25442e4089cSAndi Kleen return true; 25542e4089cSAndi Kleen if (!__pte_needs_invert(pgprot_val(prot))) 25642e4089cSAndi Kleen return true; 25742e4089cSAndi Kleen /* If it's real memory always allow */ 25842e4089cSAndi Kleen if (pfn_valid(pfn)) 25942e4089cSAndi Kleen return true; 260b0a182f8SVlastimil Babka if (pfn >= l1tf_pfn_limit() && !capable(CAP_SYS_ADMIN)) 26142e4089cSAndi Kleen return false; 26242e4089cSAndi Kleen return true; 26342e4089cSAndi Kleen } 264