1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * arch/sh/kernel/vsyscall/vsyscall.c 4 * 5 * Copyright (C) 2006 Paul Mundt 6 * 7 * vDSO randomization 8 * Copyright(C) 2005-2006, Red Hat, Inc., Ingo Molnar 9 */ 10 #include <linux/mm.h> 11 #include <linux/kernel.h> 12 #include <linux/init.h> 13 #include <linux/gfp.h> 14 #include <linux/module.h> 15 #include <linux/elf.h> 16 #include <linux/sched.h> 17 #include <linux/sysctl.h> 18 #include <linux/err.h> 19 20 /* 21 * Should the kernel map a VDSO page into processes and pass its 22 * address down to glibc upon exec()? 23 */ 24 unsigned int __read_mostly vdso_enabled = 1; 25 EXPORT_SYMBOL_GPL(vdso_enabled); 26 27 static int __init vdso_setup(char *s) 28 { 29 vdso_enabled = simple_strtoul(s, NULL, 0); 30 return 1; 31 } 32 __setup("vdso=", vdso_setup); 33 34 static const struct ctl_table vdso_table[] = { 35 { 36 .procname = "vdso_enabled", 37 .data = &vdso_enabled, 38 .maxlen = sizeof(vdso_enabled), 39 .mode = 0644, 40 .proc_handler = proc_dointvec_minmax, 41 .extra1 = SYSCTL_ZERO, 42 .extra2 = SYSCTL_ONE, 43 }, 44 }; 45 46 /* 47 * These symbols are defined by vsyscall.o to mark the bounds 48 * of the ELF DSO images included therein. 49 */ 50 extern const char vsyscall_trapa_start, vsyscall_trapa_end; 51 static struct page *syscall_pages[1]; 52 static struct vm_special_mapping vdso_mapping = { 53 .name = "[vdso]", 54 .pages = syscall_pages, 55 }; 56 57 int __init vsyscall_init(void) 58 { 59 void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC); 60 syscall_pages[0] = virt_to_page(syscall_page); 61 62 /* 63 * XXX: Map this page to a fixmap entry if we get around 64 * to adding the page to ELF core dumps 65 */ 66 67 memcpy(syscall_page, 68 &vsyscall_trapa_start, 69 &vsyscall_trapa_end - &vsyscall_trapa_start); 70 71 return 0; 72 } 73 74 static int __init vm_sysctl_init(void) 75 { 76 register_sysctl_init("vm", vdso_table); 77 return 0; 78 } 79 80 fs_initcall(vm_sysctl_init); 81 82 /* Setup a VMA at program startup for the vsyscall page */ 83 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) 84 { 85 struct mm_struct *mm = current->mm; 86 struct vm_area_struct *vma; 87 unsigned long addr; 88 int ret; 89 90 if (mmap_write_lock_killable(mm)) 91 return -EINTR; 92 93 addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); 94 if (IS_ERR_VALUE(addr)) { 95 ret = addr; 96 goto up_fail; 97 } 98 99 vdso_mapping.pages = syscall_pages; 100 vma = _install_special_mapping(mm, addr, PAGE_SIZE, 101 VM_READ | VM_EXEC | 102 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC, 103 &vdso_mapping); 104 ret = PTR_ERR(vma); 105 if (IS_ERR(vma)) 106 goto up_fail; 107 108 current->mm->context.vdso = (void *)addr; 109 ret = 0; 110 111 up_fail: 112 mmap_write_unlock(mm); 113 return ret; 114 } 115 116 const char *arch_vma_name(struct vm_area_struct *vma) 117 { 118 if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) 119 return "[vdso]"; 120 121 return NULL; 122 } 123