Skip to content

Commit 06a9750

Browse files
jpoimboeIngo Molnar
authored andcommitted
x86/entry/64: Fix unwind hints in register clearing code
The PUSH_AND_CLEAR_REGS macro zeroes each register immediately after pushing it. If an NMI or exception hits after a register is cleared, but before the UNWIND_HINT_REGS annotation, the ORC unwinder will wrongly think the previous value of the register was zero. This can confuse the unwinding process and cause it to exit early. Because ORC is simpler than DWARF, there are a limited number of unwind annotation states, so it's not possible to add an individual unwind hint after each push/clear combination. Instead, the register clearing instructions need to be consolidated and moved to after the UNWIND_HINT_REGS annotation. Fixes: 3f01dae ("x86/entry/64: Introduce the PUSH_AND_CLEAN_REGS macro") Reviewed-by: Miroslav Benes <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Cc: Andy Lutomirski <[email protected]> Cc: Dave Jones <[email protected]> Cc: Jann Horn <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Vince Weaver <[email protected]> Link: https://lore.kernel.org/r/68fd3d0bc92ae2d62ff7879d15d3684217d51f08.1587808742.git.jpoimboe@redhat.com
1 parent d8dd25a commit 06a9750

File tree

1 file changed

+21
-19
lines changed

1 file changed

+21
-19
lines changed

arch/x86/entry/calling.h

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,6 @@ For 32-bit we have the following conventions - kernel is built with
9898
#define SIZEOF_PTREGS 21*8
9999

100100
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax save_ret=0
101-
/*
102-
* Push registers and sanitize registers of values that a
103-
* speculation attack might otherwise want to exploit. The
104-
* lower registers are likely clobbered well before they
105-
* could be put to use in a speculative execution gadget.
106-
* Interleave XOR with PUSH for better uop scheduling:
107-
*/
108101
.if \save_ret
109102
pushq %rsi /* pt_regs->si */
110103
movq 8(%rsp), %rsi /* temporarily store the return address in %rsi */
@@ -114,34 +107,43 @@ For 32-bit we have the following conventions - kernel is built with
114107
pushq %rsi /* pt_regs->si */
115108
.endif
116109
pushq \rdx /* pt_regs->dx */
117-
xorl %edx, %edx /* nospec dx */
118110
pushq %rcx /* pt_regs->cx */
119-
xorl %ecx, %ecx /* nospec cx */
120111
pushq \rax /* pt_regs->ax */
121112
pushq %r8 /* pt_regs->r8 */
122-
xorl %r8d, %r8d /* nospec r8 */
123113
pushq %r9 /* pt_regs->r9 */
124-
xorl %r9d, %r9d /* nospec r9 */
125114
pushq %r10 /* pt_regs->r10 */
126-
xorl %r10d, %r10d /* nospec r10 */
127115
pushq %r11 /* pt_regs->r11 */
128-
xorl %r11d, %r11d /* nospec r11*/
129116
pushq %rbx /* pt_regs->rbx */
130-
xorl %ebx, %ebx /* nospec rbx*/
131117
pushq %rbp /* pt_regs->rbp */
132-
xorl %ebp, %ebp /* nospec rbp*/
133118
pushq %r12 /* pt_regs->r12 */
134-
xorl %r12d, %r12d /* nospec r12*/
135119
pushq %r13 /* pt_regs->r13 */
136-
xorl %r13d, %r13d /* nospec r13*/
137120
pushq %r14 /* pt_regs->r14 */
138-
xorl %r14d, %r14d /* nospec r14*/
139121
pushq %r15 /* pt_regs->r15 */
140-
xorl %r15d, %r15d /* nospec r15*/
141122
UNWIND_HINT_REGS
123+
142124
.if \save_ret
143125
pushq %rsi /* return address on top of stack */
144126
.endif
127+
128+
/*
129+
* Sanitize registers of values that a speculation attack might
130+
* otherwise want to exploit. The lower registers are likely clobbered
131+
* well before they could be put to use in a speculative execution
132+
* gadget.
133+
*/
134+
xorl %edx, %edx /* nospec dx */
135+
xorl %ecx, %ecx /* nospec cx */
136+
xorl %r8d, %r8d /* nospec r8 */
137+
xorl %r9d, %r9d /* nospec r9 */
138+
xorl %r10d, %r10d /* nospec r10 */
139+
xorl %r11d, %r11d /* nospec r11 */
140+
xorl %ebx, %ebx /* nospec rbx */
141+
xorl %ebp, %ebp /* nospec rbp */
142+
xorl %r12d, %r12d /* nospec r12 */
143+
xorl %r13d, %r13d /* nospec r13 */
144+
xorl %r14d, %r14d /* nospec r14 */
145+
xorl %r15d, %r15d /* nospec r15 */
146+
145147
.endm
146148

147149
.macro POP_REGS pop_rdi=1 skip_r11rcx=0

0 commit comments

Comments
 (0)