Skip to content

Commit 5cec93c

Browse files
amlutoIngo Molnar
authored and
Ingo Molnar
committed
x86-64: Emulate legacy vsyscalls
There's a fair amount of code in the vsyscall page. It contains a syscall instruction (in the gettimeofday fallback) and who knows what will happen if an exploit jumps into the middle of some other code. Reduce the risk by replacing the vsyscalls with short magic incantations that cause the kernel to emulate the real vsyscalls. These incantations are useless if entered in the middle. This causes vsyscalls to be a little more expensive than real syscalls. Fortunately sensible programs don't use them. The only exception is time() which is still called by glibc through the vsyscall - but calling time() millions of times per second is not sensible. glibc has this fixed in the development tree. This patch is not perfect: the vread_tsc and vread_hpet functions are still at a fixed address. Fixing that might involve making alternative patching work in the vDSO. Signed-off-by: Andy Lutomirski <[email protected]> Acked-by: Linus Torvalds <[email protected]> Cc: Jesper Juhl <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Arjan van de Ven <[email protected]> Cc: Jan Beulich <[email protected]> Cc: richard -rw- weinberger <[email protected]> Cc: Mikael Pettersson <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Louis Rilling <[email protected]> Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/e64e1b3c64858820d12c48fa739efbd1485e79d5.1307292171.git.luto@mit.edu [ Removed the CONFIG option - it's simpler to just do it unconditionally. Tidied up the code as well. ] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 5dfcea6 commit 5cec93c

File tree

9 files changed

+189
-140
lines changed

9 files changed

+189
-140
lines changed

arch/x86/include/asm/irq_vectors.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
* Vectors 0 ... 31 : system traps and exceptions - hardcoded events
1818
* Vectors 32 ... 127 : device interrupts
1919
* Vector 128 : legacy int80 syscall interface
20-
* Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 : device interrupts
20+
* Vector 204 : legacy x86_64 vsyscall emulation
21+
* Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 except 204 : device interrupts
2122
* Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
2223
*
2324
* 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table.
@@ -50,6 +51,9 @@
5051
#ifdef CONFIG_X86_32
5152
# define SYSCALL_VECTOR 0x80
5253
#endif
54+
#ifdef CONFIG_X86_64
55+
# define VSYSCALL_EMU_VECTOR 0xcc
56+
#endif
5357

5458
/*
5559
* Vectors 0x30-0x3f are used for ISA interrupts.

arch/x86/include/asm/traps.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#ifndef _ASM_X86_TRAPS_H
22
#define _ASM_X86_TRAPS_H
33

4+
#include <linux/kprobes.h>
5+
46
#include <asm/debugreg.h>
57
#include <asm/siginfo.h> /* TRAP_TRACE, ... */
68

@@ -38,6 +40,7 @@ asmlinkage void alignment_check(void);
3840
asmlinkage void machine_check(void);
3941
#endif /* CONFIG_X86_MCE */
4042
asmlinkage void simd_coprocessor_error(void);
43+
asmlinkage void emulate_vsyscall(void);
4144

4245
dotraplinkage void do_divide_error(struct pt_regs *, long);
4346
dotraplinkage void do_debug(struct pt_regs *, long);
@@ -64,6 +67,7 @@ dotraplinkage void do_alignment_check(struct pt_regs *, long);
6467
dotraplinkage void do_machine_check(struct pt_regs *, long);
6568
#endif
6669
dotraplinkage void do_simd_coprocessor_error(struct pt_regs *, long);
70+
dotraplinkage void do_emulate_vsyscall(struct pt_regs *, long);
6771
#ifdef CONFIG_X86_32
6872
dotraplinkage void do_iret_error(struct pt_regs *, long);
6973
#endif

arch/x86/include/asm/vsyscall.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ extern struct timezone sys_tz;
3131

3232
extern void map_vsyscall(void);
3333

34+
/* Emulation */
35+
36+
static inline bool is_vsyscall_entry(unsigned long addr)
37+
{
38+
return (addr & ~0xC00UL) == VSYSCALL_START;
39+
}
40+
41+
static inline int vsyscall_entry_nr(unsigned long addr)
42+
{
43+
return (addr & 0xC00UL) >> 10;
44+
}
45+
3446
#endif /* __KERNEL__ */
3547

3648
#endif /* _ASM_X86_VSYSCALL_H */

arch/x86/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ obj-y += probe_roms.o
4444
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
4545
obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
4646
obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o vread_tsc_64.o
47+
obj-$(CONFIG_X86_64) += vsyscall_emu_64.o
4748
obj-y += bootflag.o e820.o
4849
obj-y += pci-dma.o quirks.o topology.o kdebugfs.o
4950
obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o

arch/x86/kernel/entry_64.S

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,8 @@ zeroentry spurious_interrupt_bug do_spurious_interrupt_bug
11231123
zeroentry coprocessor_error do_coprocessor_error
11241124
errorentry alignment_check do_alignment_check
11251125
zeroentry simd_coprocessor_error do_simd_coprocessor_error
1126+
zeroentry emulate_vsyscall do_emulate_vsyscall
1127+
11261128

11271129
/* Reload gs selector with exception handling */
11281130
/* edi: new selector */

arch/x86/kernel/traps.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,12 @@ void __init trap_init(void)
872872
set_bit(SYSCALL_VECTOR, used_vectors);
873873
#endif
874874

875+
#ifdef CONFIG_X86_64
876+
BUG_ON(test_bit(VSYSCALL_EMU_VECTOR, used_vectors));
877+
set_system_intr_gate(VSYSCALL_EMU_VECTOR, &emulate_vsyscall);
878+
set_bit(VSYSCALL_EMU_VECTOR, used_vectors);
879+
#endif
880+
875881
/*
876882
* Should be a barrier for any external CPU state:
877883
*/

0 commit comments

Comments
 (0)