aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2015-10-05 20:48:11 -0400
committerIngo Molnar <mingo@kernel.org>2015-10-09 03:41:09 -0400
commita474e67c913d3ebaf02ba9d7835d5299d226c3ed (patch)
tree6b9ec92426db8a6e453c3748f34eda2f7cd070da
parent710246df58041106b7de645f4b45770f8a59a269 (diff)
x86/vdso/compat: Wire up SYSENTER and SYSCSALL for compat userspace
What, you didn't realize that SYSENTER and SYSCALL were actually the same thing? :) Unlike the old code, this actually passes the ptrace_syscall_32 test on AMD systems. Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/b74615af58d785aa02d917213ec64e2022a2c796.1444091585.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/entry/entry_64_compat.S90
-rw-r--r--arch/x86/entry/vdso/vdso32/system_call.S8
2 files changed, 62 insertions, 36 deletions
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 63ef9fa29002..8f109de51d03 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -52,15 +52,18 @@ ENTRY(entry_SYSENTER_compat)
52 SWAPGS_UNSAFE_STACK 52 SWAPGS_UNSAFE_STACK
53 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp 53 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
54 54
55 /* Zero-extending 32-bit regs, do not remove */ 55 /*
56 movl %ebp, %ebp 56 * User tracing code (ptrace or signal handlers) might assume that
57 * the saved RAX contains a 32-bit number when we're invoking a 32-bit
58 * syscall. Just in case the high bits are nonzero, zero-extend
59 * the syscall number. (This could almost certainly be deleted
60 * with no ill effects.)
61 */
57 movl %eax, %eax 62 movl %eax, %eax
58 63
59 movl ASM_THREAD_INFO(TI_sysenter_return, %rsp, 0), %r10d
60
61 /* Construct struct pt_regs on stack */ 64 /* Construct struct pt_regs on stack */
62 pushq $__USER32_DS /* pt_regs->ss */ 65 pushq $__USER32_DS /* pt_regs->ss */
63 pushq %rbp /* pt_regs->sp */ 66 pushq %rcx /* pt_regs->sp */
64 67
65 /* 68 /*
66 * Push flags. This is nasty. First, interrupts are currently 69 * Push flags. This is nasty. First, interrupts are currently
@@ -70,17 +73,28 @@ ENTRY(entry_SYSENTER_compat)
70 */ 73 */
71 pushfq /* pt_regs->flags (except IF = 0) */ 74 pushfq /* pt_regs->flags (except IF = 0) */
72 orl $X86_EFLAGS_IF, (%rsp) /* Fix saved flags */ 75 orl $X86_EFLAGS_IF, (%rsp) /* Fix saved flags */
76 ASM_CLAC /* Clear AC after saving FLAGS */
73 77
74 pushq $__USER32_CS /* pt_regs->cs */ 78 pushq $__USER32_CS /* pt_regs->cs */
75 pushq %r10 /* pt_regs->ip = thread_info->sysenter_return */ 79 xorq %r8,%r8
80 pushq %r8 /* pt_regs->ip = 0 (placeholder) */
76 pushq %rax /* pt_regs->orig_ax */ 81 pushq %rax /* pt_regs->orig_ax */
77 pushq %rdi /* pt_regs->di */ 82 pushq %rdi /* pt_regs->di */
78 pushq %rsi /* pt_regs->si */ 83 pushq %rsi /* pt_regs->si */
79 pushq %rdx /* pt_regs->dx */ 84 pushq %rdx /* pt_regs->dx */
80 pushq %rcx /* pt_regs->cx */ 85 pushq %rcx /* pt_regs->cx (will be overwritten) */
81 pushq $-ENOSYS /* pt_regs->ax */ 86 pushq $-ENOSYS /* pt_regs->ax */
87 pushq %r8 /* pt_regs->r8 = 0 */
88 pushq %r8 /* pt_regs->r9 = 0 */
89 pushq %r8 /* pt_regs->r10 = 0 */
90 pushq %r8 /* pt_regs->r11 = 0 */
91 pushq %rbx /* pt_regs->rbx */
92 pushq %rbp /* pt_regs->rbp */
93 pushq %r8 /* pt_regs->r12 = 0 */
94 pushq %r8 /* pt_regs->r13 = 0 */
95 pushq %r8 /* pt_regs->r14 = 0 */
96 pushq %r8 /* pt_regs->r15 = 0 */
82 cld 97 cld
83 sub $(10*8), %rsp /* pt_regs->r8-11, bp, bx, r12-15 not saved */
84 98
85 /* 99 /*
86 * Sysenter doesn't filter flags, so we need to clear NT 100 * Sysenter doesn't filter flags, so we need to clear NT
@@ -93,16 +107,15 @@ ENTRY(entry_SYSENTER_compat)
93 jnz sysenter_fix_flags 107 jnz sysenter_fix_flags
94sysenter_flags_fixed: 108sysenter_flags_fixed:
95 109
96 /* Temporary: SYSENTER is disabled. */ 110 /*
97#ifdef CONFIG_CONTEXT_TRACKING 111 * User mode is traced as though IRQs are on, and SYSENTER
98 call enter_from_user_mode 112 * turned them off.
99#endif 113 */
100 ENABLE_INTERRUPTS(CLBR_NONE) 114 TRACE_IRQS_OFF
101 movl $11, %edi
102 call do_exit
103 115
104 /* Unreachable. */ 116 movq %rsp, %rdi
105 ud2 117 call do_fast_syscall_32
118 jmp .Lsyscall_32_done
106 119
107sysenter_fix_flags: 120sysenter_fix_flags:
108 pushq $X86_EFLAGS_FIXED 121 pushq $X86_EFLAGS_FIXED
@@ -135,26 +148,14 @@ ENDPROC(entry_SYSENTER_compat)
135 * edi arg5 148 * edi arg5
136 * esp user stack 149 * esp user stack
137 * 0(%esp) arg6 150 * 0(%esp) arg6
138 *
139 * This is purely a fast path. For anything complicated we use the int 0x80
140 * path below. We set up a complete hardware stack frame to share code
141 * with the int 0x80 path.
142 */ 151 */
143ENTRY(entry_SYSCALL_compat) 152ENTRY(entry_SYSCALL_compat)
144 /* 153 /* Interrupts are off on entry. */
145 * Interrupts are off on entry.
146 * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON,
147 * it is too small to ever cause noticeable irq latency.
148 */
149 SWAPGS_UNSAFE_STACK 154 SWAPGS_UNSAFE_STACK
150 155
151 /* Temporary: SYSCALL32 is disabled. */ 156 /* Stash user ESP and switch to the kernel stack. */
152 movl $-ENOSYS, %eax
153 USERGS_SYSRET32
154
155 movl %esp, %r8d 157 movl %esp, %r8d
156 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp 158 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
157 ENABLE_INTERRUPTS(CLBR_NONE)
158 159
159 /* Zero-extending 32-bit regs, do not remove */ 160 /* Zero-extending 32-bit regs, do not remove */
160 movl %eax, %eax 161 movl %eax, %eax
@@ -169,13 +170,29 @@ ENTRY(entry_SYSCALL_compat)
169 pushq %rdi /* pt_regs->di */ 170 pushq %rdi /* pt_regs->di */
170 pushq %rsi /* pt_regs->si */ 171 pushq %rsi /* pt_regs->si */
171 pushq %rdx /* pt_regs->dx */ 172 pushq %rdx /* pt_regs->dx */
172 pushq %rbp /* pt_regs->cx */ 173 pushq %rcx /* pt_regs->cx (will be overwritten) */
173 movl %ebp, %ecx
174 pushq $-ENOSYS /* pt_regs->ax */ 174 pushq $-ENOSYS /* pt_regs->ax */
175 sub $(10*8), %rsp /* pt_regs->r8-11, bp, bx, r12-15 not saved */ 175 xorq %r8,%r8
176 pushq %r8 /* pt_regs->r8 = 0 */
177 pushq %r8 /* pt_regs->r9 = 0 */
178 pushq %r8 /* pt_regs->r10 = 0 */
179 pushq %r8 /* pt_regs->r11 = 0 */
180 pushq %rbx /* pt_regs->rbx */
181 pushq %rbp /* pt_regs->rbp */
182 pushq %r8 /* pt_regs->r12 = 0 */
183 pushq %r8 /* pt_regs->r13 = 0 */
184 pushq %r8 /* pt_regs->r14 = 0 */
185 pushq %r8 /* pt_regs->r15 = 0 */
176 186
177 /* Unreachable. */ 187 /*
178 ud2 188 * User mode is traced as though IRQs are on, and SYSENTER
189 * turned them off.
190 */
191 TRACE_IRQS_OFF
192
193 movq %rsp, %rdi
194 call do_fast_syscall_32
195 jmp .Lsyscall_32_done
179END(entry_SYSCALL_compat) 196END(entry_SYSCALL_compat)
180 197
181/* 198/*
@@ -243,6 +260,7 @@ ENTRY(entry_INT80_compat)
243 260
244 movq %rsp, %rdi 261 movq %rsp, %rdi
245 call do_int80_syscall_32 262 call do_int80_syscall_32
263.Lsyscall_32_done:
246 264
247 /* Go back to user mode. */ 265 /* Go back to user mode. */
248 TRACE_IRQS_ON 266 TRACE_IRQS_ON
diff --git a/arch/x86/entry/vdso/vdso32/system_call.S b/arch/x86/entry/vdso/vdso32/system_call.S
index d591fe93e93a..00157cae71e0 100644
--- a/arch/x86/entry/vdso/vdso32/system_call.S
+++ b/arch/x86/entry/vdso/vdso32/system_call.S
@@ -3,6 +3,8 @@
3*/ 3*/
4 4
5#include <asm/dwarf2.h> 5#include <asm/dwarf2.h>
6#include <asm/cpufeature.h>
7#include <asm/alternative-asm.h>
6 8
7/* 9/*
8 * First get the common code for the sigreturn entry points. 10 * First get the common code for the sigreturn entry points.
@@ -28,6 +30,12 @@ __kernel_vsyscall:
28 CFI_REL_OFFSET ecx, 0 30 CFI_REL_OFFSET ecx, 0
29 movl %esp, %ecx 31 movl %esp, %ecx
30 32
33#ifdef CONFIG_X86_64
34 /* If SYSENTER (Intel) or SYSCALL32 (AMD) is available, use it. */
35 ALTERNATIVE_2 "", "sysenter", X86_FEATURE_SYSENTER32, \
36 "syscall", X86_FEATURE_SYSCALL32
37#endif
38
31 /* Enter using int $0x80 */ 39 /* Enter using int $0x80 */
32 movl (%esp), %ecx 40 movl (%esp), %ecx
33 int $0x80 41 int $0x80