21 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23 #include <linux/time.h>
25 #include <linux/kernel.h>
29 #include <linux/sysctl.h>
40 #include <asm/pgtable.h>
41 #include <asm/compat.h>
43 #include <asm/unistd.h>
44 #include <asm/fixmap.h>
45 #include <asm/errno.h>
47 #include <asm/segment.h>
49 #include <asm/topology.h>
51 #include <asm/traps.h>
53 #define CREATE_TRACE_POINTS
61 static int __init vsyscall_setup(
char *
str)
64 if (!
strcmp(
"emulate", str))
66 else if (!
strcmp(
"native", str))
68 else if (!
strcmp(
"none", str))
89 write_seqcount_begin(&vdata->
seq);
92 vdata->
clock.vclock_mode = tk->
clock->archdata.vclock_mode;
93 vdata->
clock.cycle_last = tk->
clock->cycle_last;
119 write_seqcount_end(&vdata->
seq);
130 message, regs->ip, regs->
cs,
131 regs->
sp, regs->ax, regs->si, regs->di);
134 static int addr_to_vsyscall_nr(
unsigned long addr)
141 nr = (addr & 0xC00
UL) >> 10;
148 #ifdef CONFIG_SECCOMP
151 if (!seccomp_mode(&tsk->
seccomp))
158 #define vsyscall_seccomp(_tsk, _nr) 0
161 static bool write_ok_or_segv(
unsigned long ptr,
size_t size)
176 memset(&info, 0,
sizeof(info));
180 info.si_addr = (
void __user *)ptr;
194 int prev_sig_on_uaccess_error;
205 if (vsyscall_mode ==
NONE) {
207 "vsyscall attempted with vsyscall=none");
211 vsyscall_nr = addr_to_vsyscall_nr(address);
213 trace_emulate_vsyscall(vsyscall_nr);
215 if (vsyscall_nr < 0) {
217 "misaligned vsyscall (exploit attempt or buggy program) -- look up the vsyscall kernel parameter if you need a workaround");
223 "vsyscall with bad stack (exploit attempt?)");
243 switch (vsyscall_nr) {
249 if (!write_ok_or_segv(regs->di,
sizeof(
struct timeval)) ||
250 !write_ok_or_segv(regs->si,
sizeof(
struct timezone)))
263 if (!write_ok_or_segv(regs->di,
sizeof(
time_t)))
274 if (!write_ok_or_segv(regs->di,
sizeof(
unsigned)) ||
275 !write_ok_or_segv(regs->si,
sizeof(
unsigned)))
279 (
unsigned __user *)regs->si,
287 if ((
long)regs->ax <= 0
L)
295 "vsyscall fault (exploit attempt?)");
329 unsigned long node = 0;
334 write_rdtscp_aux((node << 12) | cpu);
340 d = 0x0f40000000000ULL;
342 d |= (node & 0xf) << 12;
343 d |= (node >> 4) << 48;
357 long cpu = (
long)arg;
367 extern char __vsyscall_page;
368 unsigned long physaddr_vsyscall =
__pa_symbol(&__vsyscall_page);
369 extern char __vvar_page;
370 unsigned long physaddr_vvar_page =
__pa_symbol(&__vvar_page);