1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2011 Richard Weinberger <richrd@nod.at> 4 */ 5 6 #include <linux/slab.h> 7 #include <linux/sched.h> 8 #include <linux/mm.h> 9 #include <asm/page.h> 10 #include <asm/elf.h> 11 #include <linux/init.h> 12 13 unsigned long um_vdso_addr; 14 static struct page *um_vdso; 15 16 extern unsigned long task_size; 17 extern char vdso_start[], vdso_end[]; 18 19 static int __init init_vdso(void) 20 { 21 BUG_ON(vdso_end - vdso_start > PAGE_SIZE); 22 23 um_vdso_addr = task_size - PAGE_SIZE; 24 25 um_vdso = alloc_page(GFP_KERNEL); 26 if (!um_vdso) 27 panic("Cannot allocate vdso\n"); 28 29 copy_page(page_address(um_vdso), vdso_start); 30 31 return 0; 32 } 33 subsys_initcall(init_vdso); 34 35 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 36 { 37 struct vm_area_struct *vma; 38 struct mm_struct *mm = current->mm; 39 static struct vm_special_mapping vdso_mapping = { 40 .name = "[vdso]", 41 .pages = &um_vdso, 42 }; 43 44 if (mmap_write_lock_killable(mm)) 45 return -EINTR; 46 47 vma = _install_special_mapping(mm, um_vdso_addr, PAGE_SIZE, 48 VM_READ|VM_EXEC| 49 VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC, 50 &vdso_mapping); 51 52 mmap_write_unlock(mm); 53 54 return IS_ERR(vma) ? PTR_ERR(vma) : 0; 55 } 56