Skip to content

Commit f7bafa2

Browse files
Dominik BrodowskiIngo Molnar
authored andcommitted
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 <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Brian Gerst <[email protected]> Cc: Denys Vlasenko <[email protected]> Cc: H. Peter Anvin <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 502af0d commit f7bafa2

File tree

2 files changed

+40
-30
lines changed

2 files changed

+40
-30
lines changed

arch/x86/entry/calling.h

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -101,44 +101,42 @@ For 32-bit we have the following conventions - kernel is built with
101101
addq $-(15*8), %rsp
102102
.endm
103103

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+
*/
105112
movq %rdi, 14*8+\offset(%rsp)
106113
movq %rsi, 13*8+\offset(%rsp)
107114
movq %rdx, 12*8+\offset(%rsp)
108115
movq %rcx, 11*8+\offset(%rsp)
109116
movq %rax, 10*8+\offset(%rsp)
110117
movq %r8, 9*8+\offset(%rsp)
118+
xorq %r8, %r8 /* nospec r8 */
111119
movq %r9, 8*8+\offset(%rsp)
120+
xorq %r9, %r9 /* nospec r9 */
112121
movq %r10, 7*8+\offset(%rsp)
122+
xorq %r10, %r10 /* nospec r10 */
113123
movq %r11, 6*8+\offset(%rsp)
124+
xorq %r11, %r11 /* nospec r11 */
114125
movq %rbx, 5*8+\offset(%rsp)
126+
xorl %ebx, %ebx /* nospec rbx */
115127
movq %rbp, 4*8+\offset(%rsp)
128+
xorl %ebp, %ebp /* nospec rbp */
116129
movq %r12, 3*8+\offset(%rsp)
130+
xorq %r12, %r12 /* nospec r12 */
117131
movq %r13, 2*8+\offset(%rsp)
132+
xorq %r13, %r13 /* nospec r13 */
118133
movq %r14, 1*8+\offset(%rsp)
134+
xorq %r14, %r14 /* nospec r14 */
119135
movq %r15, 0*8+\offset(%rsp)
136+
xorq %r15, %r15 /* nospec r15 */
120137
UNWIND_HINT_REGS offset=\offset
121138
.endm
122139

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-
142140
.macro POP_REGS pop_rdi=1 skip_r11rcx=0
143141
popq %r15
144142
popq %r14
@@ -177,7 +175,7 @@ For 32-bit we have the following conventions - kernel is built with
177175
* is just setting the LSB, which makes it an invalid stack address and is also
178176
* a signal to the unwinder that it's a pt_regs pointer in disguise.
179177
*
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
181179
* the original rbp.
182180
*/
183181
.macro ENCODE_FRAME_POINTER ptregs_offset=0

arch/x86/entry/entry_64.S

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,7 @@ END(irq_entries_start)
565565
1:
566566

567567
ALLOC_PT_GPREGS_ON_STACK
568-
SAVE_REGS
569-
CLEAR_REGS_NOSPEC
568+
SAVE_AND_CLEAR_REGS
570569
ENCODE_FRAME_POINTER
571570

572571
testb $3, CS(%rsp)
@@ -1114,8 +1113,7 @@ ENTRY(xen_failsafe_callback)
11141113
UNWIND_HINT_IRET_REGS
11151114
pushq $-1 /* orig_ax = -1 => not a system call */
11161115
ALLOC_PT_GPREGS_ON_STACK
1117-
SAVE_REGS
1118-
CLEAR_REGS_NOSPEC
1116+
SAVE_AND_CLEAR_REGS
11191117
ENCODE_FRAME_POINTER
11201118
jmp error_exit
11211119
END(xen_failsafe_callback)
@@ -1159,8 +1157,7 @@ idtentry machine_check do_mce has_error_code=0 paranoid=1
11591157
ENTRY(paranoid_entry)
11601158
UNWIND_HINT_FUNC
11611159
cld
1162-
SAVE_REGS 8
1163-
CLEAR_REGS_NOSPEC
1160+
SAVE_AND_CLEAR_REGS 8
11641161
ENCODE_FRAME_POINTER 8
11651162
movl $1, %ebx
11661163
movl $MSR_GS_BASE, %ecx
@@ -1211,8 +1208,7 @@ END(paranoid_exit)
12111208
ENTRY(error_entry)
12121209
UNWIND_HINT_FUNC
12131210
cld
1214-
SAVE_REGS 8
1215-
CLEAR_REGS_NOSPEC
1211+
SAVE_AND_CLEAR_REGS 8
12161212
ENCODE_FRAME_POINTER 8
12171213
testb $3, CS+8(%rsp)
12181214
jz .Lerror_kernelspace
@@ -1399,18 +1395,34 @@ ENTRY(nmi)
13991395
pushq (%rdx) /* pt_regs->dx */
14001396
pushq %rcx /* pt_regs->cx */
14011397
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+
*/
14021405
pushq %r8 /* pt_regs->r8 */
1406+
xorq %r8, %r8 /* nospec r8 */
14031407
pushq %r9 /* pt_regs->r9 */
1408+
xorq %r9, %r9 /* nospec r9 */
14041409
pushq %r10 /* pt_regs->r10 */
1410+
xorq %r10, %r10 /* nospec r10 */
14051411
pushq %r11 /* pt_regs->r11 */
1412+
xorq %r11, %r11 /* nospec r11*/
14061413
pushq %rbx /* pt_regs->rbx */
1414+
xorl %ebx, %ebx /* nospec rbx*/
14071415
pushq %rbp /* pt_regs->rbp */
1416+
xorl %ebp, %ebp /* nospec rbp*/
14081417
pushq %r12 /* pt_regs->r12 */
1418+
xorq %r12, %r12 /* nospec r12*/
14091419
pushq %r13 /* pt_regs->r13 */
1420+
xorq %r13, %r13 /* nospec r13*/
14101421
pushq %r14 /* pt_regs->r14 */
1422+
xorq %r14, %r14 /* nospec r14*/
14111423
pushq %r15 /* pt_regs->r15 */
1424+
xorq %r15, %r15 /* nospec r15*/
14121425
UNWIND_HINT_REGS
1413-
CLEAR_REGS_NOSPEC
14141426
ENCODE_FRAME_POINTER
14151427

14161428
/*

0 commit comments

Comments
 (0)