aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2018-02-11 05:49:44 -0500
committerIngo Molnar <mingo@kernel.org>2018-02-13 03:04:53 -0500
commitf7bafa2b05ef25eda1d9179fd930b0330cf2b7d1 (patch)
tree376d948cc86ebb186e30ec8c36bc9dfedf8e1271
parent502af0d70843c2a9405d7ba1f79b4b0305aaf5f5 (diff)
x86/entry/64: Interleave XOR register clearing with PUSH instructions
Same as is done for syscalls, interleave XOR with PUSH instructions for exceptions/interrupts, in order to minimize the cost of the additional instructions required for register clearing. Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net> Cc: Andy Lutomirski <luto@kernel.org> 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: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: dan.j.williams@intel.com Link: http://lkml.kernel.org/r/20180211104949.12992-4-linux@dominikbrodowski.net Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/entry/calling.h40
-rw-r--r--arch/x86/entry/entry_64.S30
2 files changed, 40 insertions, 30 deletions
diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index 3bda31736a7b..a05cbb81268d 100644
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -101,44 +101,42 @@ For 32-bit we have the following conventions - kernel is built with
101 addq $-(15*8), %rsp 101 addq $-(15*8), %rsp
102 .endm 102 .endm
103 103
104 .macro SAVE_REGS offset=0 104 .macro SAVE_AND_CLEAR_REGS offset=0
105 /*
106 * Save registers and sanitize registers of values that a
107 * speculation attack might otherwise want to exploit. The
108 * lower registers are likely clobbered well before they
109 * could be put to use in a speculative execution gadget.
110 * Interleave XOR with PUSH for better uop scheduling:
111 */
105 movq %rdi, 14*8+\offset(%rsp) 112 movq %rdi, 14*8+\offset(%rsp)
106 movq %rsi, 13*8+\offset(%rsp) 113 movq %rsi, 13*8+\offset(%rsp)
107 movq %rdx, 12*8+\offset(%rsp) 114 movq %rdx, 12*8+\offset(%rsp)
108 movq %rcx, 11*8+\offset(%rsp) 115 movq %rcx, 11*8+\offset(%rsp)
109 movq %rax, 10*8+\offset(%rsp) 116 movq %rax, 10*8+\offset(%rsp)
110 movq %r8, 9*8+\offset(%rsp) 117 movq %r8, 9*8+\offset(%rsp)
118 xorq %r8, %r8 /* nospec r8 */
111 movq %r9, 8*8+\offset(%rsp) 119 movq %r9, 8*8+\offset(%rsp)
120 xorq %r9, %r9 /* nospec r9 */
112 movq %r10, 7*8+\offset(%rsp) 121 movq %r10, 7*8+\offset(%rsp)
122 xorq %r10, %r10 /* nospec r10 */
113 movq %r11, 6*8+\offset(%rsp) 123 movq %r11, 6*8+\offset(%rsp)
124 xorq %r11, %r11 /* nospec r11 */
114 movq %rbx, 5*8+\offset(%rsp) 125 movq %rbx, 5*8+\offset(%rsp)
126 xorl %ebx, %ebx /* nospec rbx */
115 movq %rbp, 4*8+\offset(%rsp) 127 movq %rbp, 4*8+\offset(%rsp)
128 xorl %ebp, %ebp /* nospec rbp */
116 movq %r12, 3*8+\offset(%rsp) 129 movq %r12, 3*8+\offset(%rsp)
130 xorq %r12, %r12 /* nospec r12 */
117 movq %r13, 2*8+\offset(%rsp) 131 movq %r13, 2*8+\offset(%rsp)
132 xorq %r13, %r13 /* nospec r13 */
118 movq %r14, 1*8+\offset(%rsp) 133 movq %r14, 1*8+\offset(%rsp)
134 xorq %r14, %r14 /* nospec r14 */
119 movq %r15, 0*8+\offset(%rsp) 135 movq %r15, 0*8+\offset(%rsp)
136 xorq %r15, %r15 /* nospec r15 */
120 UNWIND_HINT_REGS offset=\offset 137 UNWIND_HINT_REGS offset=\offset
121 .endm 138 .endm
122 139
123 /*
124 * Sanitize registers of values that a speculation attack
125 * might otherwise want to exploit. The lower registers are
126 * likely clobbered well before they could be put to use in
127 * a speculative execution gadget:
128 */
129 .macro CLEAR_REGS_NOSPEC
130 xorl %ebp, %ebp
131 xorl %ebx, %ebx
132 xorq %r8, %r8
133 xorq %r9, %r9
134 xorq %r10, %r10
135 xorq %r11, %r11
136 xorq %r12, %r12
137 xorq %r13, %r13
138 xorq %r14, %r14
139 xorq %r15, %r15
140 .endm
141
142 .macro POP_REGS pop_rdi=1 skip_r11rcx=0 140 .macro POP_REGS pop_rdi=1 skip_r11rcx=0
143 popq %r15 141 popq %r15
144 popq %r14 142 popq %r14
@@ -177,7 +175,7 @@ For 32-bit we have the following conventions - kernel is built with
177 * is just setting the LSB, which makes it an invalid stack address and is also 175 * is just setting the LSB, which makes it an invalid stack address and is also
178 * a signal to the unwinder that it's a pt_regs pointer in disguise. 176 * a signal to the unwinder that it's a pt_regs pointer in disguise.
179 * 177 *
180 * NOTE: This macro must be used *after* SAVE_REGS because it corrupts 178 * NOTE: This macro must be used *after* SAVE_AND_CLEAR_REGS because it corrupts
181 * the original rbp. 179 * the original rbp.
182 */ 180 */
183.macro ENCODE_FRAME_POINTER ptregs_offset=0 181.macro ENCODE_FRAME_POINTER ptregs_offset=0
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 7351c91fb7df..07692b44800d 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -565,8 +565,7 @@ END(irq_entries_start)
5651: 5651:
566 566
567 ALLOC_PT_GPREGS_ON_STACK 567 ALLOC_PT_GPREGS_ON_STACK
568 SAVE_REGS 568 SAVE_AND_CLEAR_REGS
569 CLEAR_REGS_NOSPEC
570 ENCODE_FRAME_POINTER 569 ENCODE_FRAME_POINTER
571 570
572 testb $3, CS(%rsp) 571 testb $3, CS(%rsp)
@@ -1114,8 +1113,7 @@ ENTRY(xen_failsafe_callback)
1114 UNWIND_HINT_IRET_REGS 1113 UNWIND_HINT_IRET_REGS
1115 pushq $-1 /* orig_ax = -1 => not a system call */ 1114 pushq $-1 /* orig_ax = -1 => not a system call */
1116 ALLOC_PT_GPREGS_ON_STACK 1115 ALLOC_PT_GPREGS_ON_STACK
1117 SAVE_REGS 1116 SAVE_AND_CLEAR_REGS
1118 CLEAR_REGS_NOSPEC
1119 ENCODE_FRAME_POINTER 1117 ENCODE_FRAME_POINTER
1120 jmp error_exit 1118 jmp error_exit
1121END(xen_failsafe_callback) 1119END(xen_failsafe_callback)
@@ -1159,8 +1157,7 @@ idtentry machine_check do_mce has_error_code=0 paranoid=1
1159ENTRY(paranoid_entry) 1157ENTRY(paranoid_entry)
1160 UNWIND_HINT_FUNC 1158 UNWIND_HINT_FUNC
1161 cld 1159 cld
1162 SAVE_REGS 8 1160 SAVE_AND_CLEAR_REGS 8
1163 CLEAR_REGS_NOSPEC
1164 ENCODE_FRAME_POINTER 8 1161 ENCODE_FRAME_POINTER 8
1165 movl $1, %ebx 1162 movl $1, %ebx
1166 movl $MSR_GS_BASE, %ecx 1163 movl $MSR_GS_BASE, %ecx
@@ -1211,8 +1208,7 @@ END(paranoid_exit)
1211ENTRY(error_entry) 1208ENTRY(error_entry)
1212 UNWIND_HINT_FUNC 1209 UNWIND_HINT_FUNC
1213 cld 1210 cld
1214 SAVE_REGS 8 1211 SAVE_AND_CLEAR_REGS 8
1215 CLEAR_REGS_NOSPEC
1216 ENCODE_FRAME_POINTER 8 1212 ENCODE_FRAME_POINTER 8
1217 testb $3, CS+8(%rsp) 1213 testb $3, CS+8(%rsp)
1218 jz .Lerror_kernelspace 1214 jz .Lerror_kernelspace
@@ -1399,18 +1395,34 @@ ENTRY(nmi)
1399 pushq (%rdx) /* pt_regs->dx */ 1395 pushq (%rdx) /* pt_regs->dx */
1400 pushq %rcx /* pt_regs->cx */ 1396 pushq %rcx /* pt_regs->cx */
1401 pushq %rax /* pt_regs->ax */ 1397 pushq %rax /* pt_regs->ax */
1398 /*
1399 * Sanitize registers of values that a speculation attack
1400 * might otherwise want to exploit. The lower registers are
1401 * likely clobbered well before they could be put to use in
1402 * a speculative execution gadget. Interleave XOR with PUSH
1403 * for better uop scheduling:
1404 */
1402 pushq %r8 /* pt_regs->r8 */ 1405 pushq %r8 /* pt_regs->r8 */
1406 xorq %r8, %r8 /* nospec r8 */
1403 pushq %r9 /* pt_regs->r9 */ 1407 pushq %r9 /* pt_regs->r9 */
1408 xorq %r9, %r9 /* nospec r9 */
1404 pushq %r10 /* pt_regs->r10 */ 1409 pushq %r10 /* pt_regs->r10 */
1410 xorq %r10, %r10 /* nospec r10 */
1405 pushq %r11 /* pt_regs->r11 */ 1411 pushq %r11 /* pt_regs->r11 */
1412 xorq %r11, %r11 /* nospec r11*/
1406 pushq %rbx /* pt_regs->rbx */ 1413 pushq %rbx /* pt_regs->rbx */
1414 xorl %ebx, %ebx /* nospec rbx*/
1407 pushq %rbp /* pt_regs->rbp */ 1415 pushq %rbp /* pt_regs->rbp */
1416 xorl %ebp, %ebp /* nospec rbp*/
1408 pushq %r12 /* pt_regs->r12 */ 1417 pushq %r12 /* pt_regs->r12 */
1418 xorq %r12, %r12 /* nospec r12*/
1409 pushq %r13 /* pt_regs->r13 */ 1419 pushq %r13 /* pt_regs->r13 */
1420 xorq %r13, %r13 /* nospec r13*/
1410 pushq %r14 /* pt_regs->r14 */ 1421 pushq %r14 /* pt_regs->r14 */
1422 xorq %r14, %r14 /* nospec r14*/
1411 pushq %r15 /* pt_regs->r15 */ 1423 pushq %r15 /* pt_regs->r15 */
1424 xorq %r15, %r15 /* nospec r15*/
1412 UNWIND_HINT_REGS 1425 UNWIND_HINT_REGS
1413 CLEAR_REGS_NOSPEC
1414 ENCODE_FRAME_POINTER 1426 ENCODE_FRAME_POINTER
1415 1427
1416 /* 1428 /*