1caab277bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 29031fefdSWill Deacon /* 30d747f65SVincenzo Frascino * VDSO implementations. 49031fefdSWill Deacon * 59031fefdSWill Deacon * Copyright (C) 2012 ARM Limited 69031fefdSWill Deacon * 79031fefdSWill Deacon * Author: Will Deacon <will.deacon@arm.com> 89031fefdSWill Deacon */ 99031fefdSWill Deacon 105a9e3e15SJisheng Zhang #include <linux/cache.h> 119031fefdSWill Deacon #include <linux/clocksource.h> 129031fefdSWill Deacon #include <linux/elf.h> 139031fefdSWill Deacon #include <linux/err.h> 149031fefdSWill Deacon #include <linux/errno.h> 159031fefdSWill Deacon #include <linux/gfp.h> 165a9e3e15SJisheng Zhang #include <linux/kernel.h> 179031fefdSWill Deacon #include <linux/mm.h> 189031fefdSWill Deacon #include <linux/sched.h> 199031fefdSWill Deacon #include <linux/signal.h> 209031fefdSWill Deacon #include <linux/slab.h> 21c60b0c28SCatalin Marinas #include <linux/timekeeper_internal.h> 229031fefdSWill Deacon #include <linux/vmalloc.h> 2328b1a824SVincenzo Frascino #include <vdso/datapage.h> 2428b1a824SVincenzo Frascino #include <vdso/helpers.h> 2528b1a824SVincenzo Frascino #include <vdso/vsyscall.h> 269031fefdSWill Deacon 279031fefdSWill Deacon #include <asm/cacheflush.h> 289031fefdSWill Deacon #include <asm/signal32.h> 299031fefdSWill Deacon #include <asm/vdso.h> 309031fefdSWill Deacon 31dbbb08f5SKees Cook extern char vdso_start[], vdso_end[]; 327c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 337c1deeebSVincenzo Frascino extern char vdso32_start[], vdso32_end[]; 347c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 35c7aa2d71SVincenzo Frascino 36c7aa2d71SVincenzo Frascino /* vdso_lookup arch_index */ 37c7aa2d71SVincenzo Frascino enum arch_vdso_type { 38c7aa2d71SVincenzo Frascino ARM64_VDSO = 0, 397c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 407c1deeebSVincenzo Frascino ARM64_VDSO32 = 1, 417c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 42c7aa2d71SVincenzo Frascino }; 437c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 447c1deeebSVincenzo Frascino #define VDSO_TYPES (ARM64_VDSO32 + 1) 457c1deeebSVincenzo Frascino #else 46c7aa2d71SVincenzo Frascino #define VDSO_TYPES (ARM64_VDSO + 1) 477c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 48c7aa2d71SVincenzo Frascino 49c7aa2d71SVincenzo Frascino struct __vdso_abi { 50c7aa2d71SVincenzo Frascino const char *name; 51c7aa2d71SVincenzo Frascino const char *vdso_code_start; 52c7aa2d71SVincenzo Frascino const char *vdso_code_end; 53c7aa2d71SVincenzo Frascino unsigned long vdso_pages; 54c7aa2d71SVincenzo Frascino /* Data Mapping */ 55c7aa2d71SVincenzo Frascino struct vm_special_mapping *dm; 56c7aa2d71SVincenzo Frascino /* Code Mapping */ 57c7aa2d71SVincenzo Frascino struct vm_special_mapping *cm; 58c7aa2d71SVincenzo Frascino }; 59c7aa2d71SVincenzo Frascino 60c7aa2d71SVincenzo Frascino static struct __vdso_abi vdso_lookup[VDSO_TYPES] __ro_after_init = { 61c7aa2d71SVincenzo Frascino { 62c7aa2d71SVincenzo Frascino .name = "vdso", 63c7aa2d71SVincenzo Frascino .vdso_code_start = vdso_start, 64c7aa2d71SVincenzo Frascino .vdso_code_end = vdso_end, 65c7aa2d71SVincenzo Frascino }, 667c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 677c1deeebSVincenzo Frascino { 687c1deeebSVincenzo Frascino .name = "vdso32", 697c1deeebSVincenzo Frascino .vdso_code_start = vdso32_start, 707c1deeebSVincenzo Frascino .vdso_code_end = vdso32_end, 717c1deeebSVincenzo Frascino }, 727c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 73c7aa2d71SVincenzo Frascino }; 749031fefdSWill Deacon 759031fefdSWill Deacon /* 769031fefdSWill Deacon * The vDSO data page. 779031fefdSWill Deacon */ 789031fefdSWill Deacon static union { 7928b1a824SVincenzo Frascino struct vdso_data data[CS_BASES]; 809031fefdSWill Deacon u8 page[PAGE_SIZE]; 819031fefdSWill Deacon } vdso_data_store __page_aligned_data; 8228b1a824SVincenzo Frascino struct vdso_data *vdso_data = vdso_data_store.data; 839031fefdSWill Deacon 84c7aa2d71SVincenzo Frascino static int __vdso_remap(enum arch_vdso_type arch_index, 85c7aa2d71SVincenzo Frascino const struct vm_special_mapping *sm, 86c7aa2d71SVincenzo Frascino struct vm_area_struct *new_vma) 87c7aa2d71SVincenzo Frascino { 88c7aa2d71SVincenzo Frascino unsigned long new_size = new_vma->vm_end - new_vma->vm_start; 89c7aa2d71SVincenzo Frascino unsigned long vdso_size = vdso_lookup[arch_index].vdso_code_end - 90c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].vdso_code_start; 91c7aa2d71SVincenzo Frascino 92c7aa2d71SVincenzo Frascino if (vdso_size != new_size) 93c7aa2d71SVincenzo Frascino return -EINVAL; 94c7aa2d71SVincenzo Frascino 95c7aa2d71SVincenzo Frascino current->mm->context.vdso = (void *)new_vma->vm_start; 96c7aa2d71SVincenzo Frascino 97c7aa2d71SVincenzo Frascino return 0; 98c7aa2d71SVincenzo Frascino } 99c7aa2d71SVincenzo Frascino 100c7aa2d71SVincenzo Frascino static int __vdso_init(enum arch_vdso_type arch_index) 101c7aa2d71SVincenzo Frascino { 102c7aa2d71SVincenzo Frascino int i; 103c7aa2d71SVincenzo Frascino struct page **vdso_pagelist; 104c7aa2d71SVincenzo Frascino unsigned long pfn; 105c7aa2d71SVincenzo Frascino 106c7aa2d71SVincenzo Frascino if (memcmp(vdso_lookup[arch_index].vdso_code_start, "\177ELF", 4)) { 107c7aa2d71SVincenzo Frascino pr_err("vDSO is not a valid ELF object!\n"); 108c7aa2d71SVincenzo Frascino return -EINVAL; 109c7aa2d71SVincenzo Frascino } 110c7aa2d71SVincenzo Frascino 111c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].vdso_pages = ( 112c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].vdso_code_end - 113c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].vdso_code_start) >> 114c7aa2d71SVincenzo Frascino PAGE_SHIFT; 115c7aa2d71SVincenzo Frascino 116c7aa2d71SVincenzo Frascino /* Allocate the vDSO pagelist, plus a page for the data. */ 117c7aa2d71SVincenzo Frascino vdso_pagelist = kcalloc(vdso_lookup[arch_index].vdso_pages + 1, 118c7aa2d71SVincenzo Frascino sizeof(struct page *), 119c7aa2d71SVincenzo Frascino GFP_KERNEL); 120c7aa2d71SVincenzo Frascino if (vdso_pagelist == NULL) 121c7aa2d71SVincenzo Frascino return -ENOMEM; 122c7aa2d71SVincenzo Frascino 123c7aa2d71SVincenzo Frascino /* Grab the vDSO data page. */ 124c7aa2d71SVincenzo Frascino vdso_pagelist[0] = phys_to_page(__pa_symbol(vdso_data)); 125c7aa2d71SVincenzo Frascino 126c7aa2d71SVincenzo Frascino 127c7aa2d71SVincenzo Frascino /* Grab the vDSO code pages. */ 128c7aa2d71SVincenzo Frascino pfn = sym_to_pfn(vdso_lookup[arch_index].vdso_code_start); 129c7aa2d71SVincenzo Frascino 130c7aa2d71SVincenzo Frascino for (i = 0; i < vdso_lookup[arch_index].vdso_pages; i++) 131c7aa2d71SVincenzo Frascino vdso_pagelist[i + 1] = pfn_to_page(pfn + i); 132c7aa2d71SVincenzo Frascino 133c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].dm->pages = &vdso_pagelist[0]; 134c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].cm->pages = &vdso_pagelist[1]; 135c7aa2d71SVincenzo Frascino 136c7aa2d71SVincenzo Frascino return 0; 137c7aa2d71SVincenzo Frascino } 138c7aa2d71SVincenzo Frascino 139c7aa2d71SVincenzo Frascino static int __setup_additional_pages(enum arch_vdso_type arch_index, 140c7aa2d71SVincenzo Frascino struct mm_struct *mm, 141c7aa2d71SVincenzo Frascino struct linux_binprm *bprm, 142c7aa2d71SVincenzo Frascino int uses_interp) 143c7aa2d71SVincenzo Frascino { 144c7aa2d71SVincenzo Frascino unsigned long vdso_base, vdso_text_len, vdso_mapping_len; 145bf740a90SMark Brown unsigned long gp_flags = 0; 146c7aa2d71SVincenzo Frascino void *ret; 147c7aa2d71SVincenzo Frascino 148c7aa2d71SVincenzo Frascino vdso_text_len = vdso_lookup[arch_index].vdso_pages << PAGE_SHIFT; 149c7aa2d71SVincenzo Frascino /* Be sure to map the data page */ 150c7aa2d71SVincenzo Frascino vdso_mapping_len = vdso_text_len + PAGE_SIZE; 151c7aa2d71SVincenzo Frascino 152c7aa2d71SVincenzo Frascino vdso_base = get_unmapped_area(NULL, 0, vdso_mapping_len, 0, 0); 153c7aa2d71SVincenzo Frascino if (IS_ERR_VALUE(vdso_base)) { 154c7aa2d71SVincenzo Frascino ret = ERR_PTR(vdso_base); 155c7aa2d71SVincenzo Frascino goto up_fail; 156c7aa2d71SVincenzo Frascino } 157c7aa2d71SVincenzo Frascino 158c7aa2d71SVincenzo Frascino ret = _install_special_mapping(mm, vdso_base, PAGE_SIZE, 159c7aa2d71SVincenzo Frascino VM_READ|VM_MAYREAD, 160c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].dm); 161c7aa2d71SVincenzo Frascino if (IS_ERR(ret)) 162c7aa2d71SVincenzo Frascino goto up_fail; 163c7aa2d71SVincenzo Frascino 164bf740a90SMark Brown if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) && system_supports_bti()) 165bf740a90SMark Brown gp_flags = VM_ARM64_BTI; 166bf740a90SMark Brown 167c7aa2d71SVincenzo Frascino vdso_base += PAGE_SIZE; 168c7aa2d71SVincenzo Frascino mm->context.vdso = (void *)vdso_base; 169c7aa2d71SVincenzo Frascino ret = _install_special_mapping(mm, vdso_base, vdso_text_len, 170bf740a90SMark Brown VM_READ|VM_EXEC|gp_flags| 171c7aa2d71SVincenzo Frascino VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, 172c7aa2d71SVincenzo Frascino vdso_lookup[arch_index].cm); 173c7aa2d71SVincenzo Frascino if (IS_ERR(ret)) 174c7aa2d71SVincenzo Frascino goto up_fail; 175c7aa2d71SVincenzo Frascino 176c7aa2d71SVincenzo Frascino return 0; 177c7aa2d71SVincenzo Frascino 178c7aa2d71SVincenzo Frascino up_fail: 179c7aa2d71SVincenzo Frascino mm->context.vdso = NULL; 180c7aa2d71SVincenzo Frascino return PTR_ERR(ret); 181c7aa2d71SVincenzo Frascino } 182c7aa2d71SVincenzo Frascino 1839031fefdSWill Deacon #ifdef CONFIG_COMPAT 1849031fefdSWill Deacon /* 1859031fefdSWill Deacon * Create and map the vectors page for AArch32 tasks. 1869031fefdSWill Deacon */ 1877c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 1887c1deeebSVincenzo Frascino static int aarch32_vdso_mremap(const struct vm_special_mapping *sm, 1897c1deeebSVincenzo Frascino struct vm_area_struct *new_vma) 1907c1deeebSVincenzo Frascino { 1917c1deeebSVincenzo Frascino return __vdso_remap(ARM64_VDSO32, sm, new_vma); 1927c1deeebSVincenzo Frascino } 1937c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 1947c1deeebSVincenzo Frascino 195c7aa2d71SVincenzo Frascino /* 196c7aa2d71SVincenzo Frascino * aarch32_vdso_pages: 197c7aa2d71SVincenzo Frascino * 0 - kuser helpers 198c7aa2d71SVincenzo Frascino * 1 - sigreturn code 1997c1deeebSVincenzo Frascino * or (CONFIG_COMPAT_VDSO): 2007c1deeebSVincenzo Frascino * 0 - kuser helpers 2017c1deeebSVincenzo Frascino * 1 - vdso data 2027c1deeebSVincenzo Frascino * 2 - vdso code 203c7aa2d71SVincenzo Frascino */ 2040d747f65SVincenzo Frascino #define C_VECTORS 0 2057c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 2067c1deeebSVincenzo Frascino #define C_VVAR 1 2077c1deeebSVincenzo Frascino #define C_VDSO 2 2087c1deeebSVincenzo Frascino #define C_PAGES (C_VDSO + 1) 2097c1deeebSVincenzo Frascino #else 2100d747f65SVincenzo Frascino #define C_SIGPAGE 1 2110d747f65SVincenzo Frascino #define C_PAGES (C_SIGPAGE + 1) 2127c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 2130d747f65SVincenzo Frascino static struct page *aarch32_vdso_pages[C_PAGES] __ro_after_init; 2147c1deeebSVincenzo Frascino static struct vm_special_mapping aarch32_vdso_spec[C_PAGES] = { 2150d747f65SVincenzo Frascino { 2160d747f65SVincenzo Frascino .name = "[vectors]", /* ABI */ 2170d747f65SVincenzo Frascino .pages = &aarch32_vdso_pages[C_VECTORS], 2180d747f65SVincenzo Frascino }, 2197c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 2207c1deeebSVincenzo Frascino { 2217c1deeebSVincenzo Frascino .name = "[vvar]", 2227c1deeebSVincenzo Frascino }, 2237c1deeebSVincenzo Frascino { 2247c1deeebSVincenzo Frascino .name = "[vdso]", 2257c1deeebSVincenzo Frascino .mremap = aarch32_vdso_mremap, 2267c1deeebSVincenzo Frascino }, 2277c1deeebSVincenzo Frascino #else 2280d747f65SVincenzo Frascino { 2290d747f65SVincenzo Frascino .name = "[sigpage]", /* ABI */ 2300d747f65SVincenzo Frascino .pages = &aarch32_vdso_pages[C_SIGPAGE], 2310d747f65SVincenzo Frascino }, 2327c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 2330d747f65SVincenzo Frascino }; 2349031fefdSWill Deacon 2351255a734SVincenzo Frascino static int aarch32_alloc_kuser_vdso_page(void) 2369031fefdSWill Deacon { 2379031fefdSWill Deacon extern char __kuser_helper_start[], __kuser_helper_end[]; 2389031fefdSWill Deacon int kuser_sz = __kuser_helper_end - __kuser_helper_start; 2391255a734SVincenzo Frascino unsigned long vdso_page; 2409031fefdSWill Deacon 241af1b3cf2SVincenzo Frascino if (!IS_ENABLED(CONFIG_KUSER_HELPERS)) 242af1b3cf2SVincenzo Frascino return 0; 243af1b3cf2SVincenzo Frascino 2441255a734SVincenzo Frascino vdso_page = get_zeroed_page(GFP_ATOMIC); 2451255a734SVincenzo Frascino if (!vdso_page) 2469031fefdSWill Deacon return -ENOMEM; 2479031fefdSWill Deacon 2481255a734SVincenzo Frascino memcpy((void *)(vdso_page + 0x1000 - kuser_sz), __kuser_helper_start, 2491255a734SVincenzo Frascino kuser_sz); 2501255a734SVincenzo Frascino aarch32_vdso_pages[C_VECTORS] = virt_to_page(vdso_page); 2511255a734SVincenzo Frascino flush_dcache_page(aarch32_vdso_pages[C_VECTORS]); 2521255a734SVincenzo Frascino return 0; 2530d747f65SVincenzo Frascino } 2540d747f65SVincenzo Frascino 2557c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 2567c1deeebSVincenzo Frascino static int __aarch32_alloc_vdso_pages(void) 2577c1deeebSVincenzo Frascino { 2587c1deeebSVincenzo Frascino int ret; 2597c1deeebSVincenzo Frascino 2607c1deeebSVincenzo Frascino vdso_lookup[ARM64_VDSO32].dm = &aarch32_vdso_spec[C_VVAR]; 2617c1deeebSVincenzo Frascino vdso_lookup[ARM64_VDSO32].cm = &aarch32_vdso_spec[C_VDSO]; 2627c1deeebSVincenzo Frascino 2637c1deeebSVincenzo Frascino ret = __vdso_init(ARM64_VDSO32); 2647c1deeebSVincenzo Frascino if (ret) 2657c1deeebSVincenzo Frascino return ret; 2667c1deeebSVincenzo Frascino 2679cc3d0c6SMark Rutland return aarch32_alloc_kuser_vdso_page(); 2687c1deeebSVincenzo Frascino } 2697c1deeebSVincenzo Frascino #else 2707c1deeebSVincenzo Frascino static int __aarch32_alloc_vdso_pages(void) 2711255a734SVincenzo Frascino { 2721255a734SVincenzo Frascino extern char __aarch32_sigret_code_start[], __aarch32_sigret_code_end[]; 2731255a734SVincenzo Frascino int sigret_sz = __aarch32_sigret_code_end - __aarch32_sigret_code_start; 2741255a734SVincenzo Frascino unsigned long sigpage; 2751255a734SVincenzo Frascino int ret; 2769031fefdSWill Deacon 2771255a734SVincenzo Frascino sigpage = get_zeroed_page(GFP_ATOMIC); 2781255a734SVincenzo Frascino if (!sigpage) 2791255a734SVincenzo Frascino return -ENOMEM; 2809031fefdSWill Deacon 2811255a734SVincenzo Frascino memcpy((void *)sigpage, __aarch32_sigret_code_start, sigret_sz); 2821255a734SVincenzo Frascino aarch32_vdso_pages[C_SIGPAGE] = virt_to_page(sigpage); 2831255a734SVincenzo Frascino flush_dcache_page(aarch32_vdso_pages[C_SIGPAGE]); 2840d747f65SVincenzo Frascino 2851255a734SVincenzo Frascino ret = aarch32_alloc_kuser_vdso_page(); 2861255a734SVincenzo Frascino if (ret) 2871255a734SVincenzo Frascino free_page(sigpage); 2889031fefdSWill Deacon 2891255a734SVincenzo Frascino return ret; 2909031fefdSWill Deacon } 2917c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 2927c1deeebSVincenzo Frascino 2937c1deeebSVincenzo Frascino static int __init aarch32_alloc_vdso_pages(void) 2947c1deeebSVincenzo Frascino { 2957c1deeebSVincenzo Frascino return __aarch32_alloc_vdso_pages(); 2967c1deeebSVincenzo Frascino } 2970d747f65SVincenzo Frascino arch_initcall(aarch32_alloc_vdso_pages); 2989031fefdSWill Deacon 2990d747f65SVincenzo Frascino static int aarch32_kuser_helpers_setup(struct mm_struct *mm) 3000d747f65SVincenzo Frascino { 3010d747f65SVincenzo Frascino void *ret; 3020d747f65SVincenzo Frascino 303af1b3cf2SVincenzo Frascino if (!IS_ENABLED(CONFIG_KUSER_HELPERS)) 304af1b3cf2SVincenzo Frascino return 0; 305af1b3cf2SVincenzo Frascino 3060d747f65SVincenzo Frascino /* 3070d747f65SVincenzo Frascino * Avoid VM_MAYWRITE for compatibility with arch/arm/, where it's 3080d747f65SVincenzo Frascino * not safe to CoW the page containing the CPU exception vectors. 3090d747f65SVincenzo Frascino */ 3100d747f65SVincenzo Frascino ret = _install_special_mapping(mm, AARCH32_VECTORS_BASE, PAGE_SIZE, 3110d747f65SVincenzo Frascino VM_READ | VM_EXEC | 3120d747f65SVincenzo Frascino VM_MAYREAD | VM_MAYEXEC, 3130d747f65SVincenzo Frascino &aarch32_vdso_spec[C_VECTORS]); 3140d747f65SVincenzo Frascino 3150d747f65SVincenzo Frascino return PTR_ERR_OR_ZERO(ret); 3160d747f65SVincenzo Frascino } 3170d747f65SVincenzo Frascino 3187c1deeebSVincenzo Frascino #ifndef CONFIG_COMPAT_VDSO 3190d747f65SVincenzo Frascino static int aarch32_sigreturn_setup(struct mm_struct *mm) 3200d747f65SVincenzo Frascino { 3210d747f65SVincenzo Frascino unsigned long addr; 3220d747f65SVincenzo Frascino void *ret; 3230d747f65SVincenzo Frascino 3240d747f65SVincenzo Frascino addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); 3250d747f65SVincenzo Frascino if (IS_ERR_VALUE(addr)) { 3260d747f65SVincenzo Frascino ret = ERR_PTR(addr); 3270d747f65SVincenzo Frascino goto out; 3280d747f65SVincenzo Frascino } 3290d747f65SVincenzo Frascino 3300d747f65SVincenzo Frascino /* 3310d747f65SVincenzo Frascino * VM_MAYWRITE is required to allow gdb to Copy-on-Write and 3320d747f65SVincenzo Frascino * set breakpoints. 3330d747f65SVincenzo Frascino */ 3340d747f65SVincenzo Frascino ret = _install_special_mapping(mm, addr, PAGE_SIZE, 3350d747f65SVincenzo Frascino VM_READ | VM_EXEC | VM_MAYREAD | 3360d747f65SVincenzo Frascino VM_MAYWRITE | VM_MAYEXEC, 3370d747f65SVincenzo Frascino &aarch32_vdso_spec[C_SIGPAGE]); 3380d747f65SVincenzo Frascino if (IS_ERR(ret)) 3390d747f65SVincenzo Frascino goto out; 3400d747f65SVincenzo Frascino 3410d747f65SVincenzo Frascino mm->context.vdso = (void *)addr; 3420d747f65SVincenzo Frascino 3430d747f65SVincenzo Frascino out: 3440d747f65SVincenzo Frascino return PTR_ERR_OR_ZERO(ret); 3450d747f65SVincenzo Frascino } 3467c1deeebSVincenzo Frascino #endif /* !CONFIG_COMPAT_VDSO */ 3470d747f65SVincenzo Frascino 3480d747f65SVincenzo Frascino int aarch32_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 3499031fefdSWill Deacon { 3509031fefdSWill Deacon struct mm_struct *mm = current->mm; 3510d747f65SVincenzo Frascino int ret; 3529031fefdSWill Deacon 35369048176SMichal Hocko if (down_write_killable(&mm->mmap_sem)) 35469048176SMichal Hocko return -EINTR; 3559031fefdSWill Deacon 3560d747f65SVincenzo Frascino ret = aarch32_kuser_helpers_setup(mm); 3570d747f65SVincenzo Frascino if (ret) 3580d747f65SVincenzo Frascino goto out; 3599031fefdSWill Deacon 3607c1deeebSVincenzo Frascino #ifdef CONFIG_COMPAT_VDSO 3617c1deeebSVincenzo Frascino ret = __setup_additional_pages(ARM64_VDSO32, 3627c1deeebSVincenzo Frascino mm, 3637c1deeebSVincenzo Frascino bprm, 3647c1deeebSVincenzo Frascino uses_interp); 3657c1deeebSVincenzo Frascino #else 3660d747f65SVincenzo Frascino ret = aarch32_sigreturn_setup(mm); 3677c1deeebSVincenzo Frascino #endif /* CONFIG_COMPAT_VDSO */ 3680d747f65SVincenzo Frascino 3690d747f65SVincenzo Frascino out: 3709031fefdSWill Deacon up_write(&mm->mmap_sem); 3710d747f65SVincenzo Frascino return ret; 3729031fefdSWill Deacon } 3739031fefdSWill Deacon #endif /* CONFIG_COMPAT */ 3749031fefdSWill Deacon 37573958695SDmitry Safonov static int vdso_mremap(const struct vm_special_mapping *sm, 37673958695SDmitry Safonov struct vm_area_struct *new_vma) 37773958695SDmitry Safonov { 378c7aa2d71SVincenzo Frascino return __vdso_remap(ARM64_VDSO, sm, new_vma); 37973958695SDmitry Safonov } 38073958695SDmitry Safonov 381c7aa2d71SVincenzo Frascino /* 382c7aa2d71SVincenzo Frascino * aarch64_vdso_pages: 383c7aa2d71SVincenzo Frascino * 0 - vvar 384c7aa2d71SVincenzo Frascino * 1 - vdso 385c7aa2d71SVincenzo Frascino */ 386c7aa2d71SVincenzo Frascino #define A_VVAR 0 387c7aa2d71SVincenzo Frascino #define A_VDSO 1 388c7aa2d71SVincenzo Frascino #define A_PAGES (A_VDSO + 1) 389c7aa2d71SVincenzo Frascino static struct vm_special_mapping vdso_spec[A_PAGES] __ro_after_init = { 3905a9e3e15SJisheng Zhang { 3915a9e3e15SJisheng Zhang .name = "[vvar]", 3925a9e3e15SJisheng Zhang }, 3935a9e3e15SJisheng Zhang { 3945a9e3e15SJisheng Zhang .name = "[vdso]", 39573958695SDmitry Safonov .mremap = vdso_mremap, 3965a9e3e15SJisheng Zhang }, 3975a9e3e15SJisheng Zhang }; 3982fea7f6cSWill Deacon 3999031fefdSWill Deacon static int __init vdso_init(void) 4009031fefdSWill Deacon { 401c7aa2d71SVincenzo Frascino vdso_lookup[ARM64_VDSO].dm = &vdso_spec[A_VVAR]; 402c7aa2d71SVincenzo Frascino vdso_lookup[ARM64_VDSO].cm = &vdso_spec[A_VDSO]; 40316fb1a9bSNathan Lynch 404c7aa2d71SVincenzo Frascino return __vdso_init(ARM64_VDSO); 4059031fefdSWill Deacon } 4069031fefdSWill Deacon arch_initcall(vdso_init); 4079031fefdSWill Deacon 4089031fefdSWill Deacon int arch_setup_additional_pages(struct linux_binprm *bprm, 4099031fefdSWill Deacon int uses_interp) 4109031fefdSWill Deacon { 4119031fefdSWill Deacon struct mm_struct *mm = current->mm; 412c7aa2d71SVincenzo Frascino int ret; 4139031fefdSWill Deacon 41469048176SMichal Hocko if (down_write_killable(&mm->mmap_sem)) 41569048176SMichal Hocko return -EINTR; 41687154938SWill Deacon 417c7aa2d71SVincenzo Frascino ret = __setup_additional_pages(ARM64_VDSO, 418c7aa2d71SVincenzo Frascino mm, 419c7aa2d71SVincenzo Frascino bprm, 420c7aa2d71SVincenzo Frascino uses_interp); 421601255aeSWill Deacon 42287154938SWill Deacon up_write(&mm->mmap_sem); 4239031fefdSWill Deacon 424c7aa2d71SVincenzo Frascino return ret; 4259031fefdSWill Deacon } 426