xref: /linux/arch/sh/kernel/vsyscall/vsyscall.c (revision 592329e5e94e26080f4815c6cc6cd0f487a91064)
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 
vdso_setup(char * s)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 
vsyscall_init(void)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 
vm_sysctl_init(void)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 */
arch_setup_additional_pages(struct linux_binprm * bprm,int uses_interp)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 
arch_vma_name(struct vm_area_struct * vma)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