Skip to content

Commit d4667ca

Browse files
committed
Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 PTI and Spectre related fixes and updates from Ingo Molnar: "Here's the latest set of Spectre and PTI related fixes and updates: Spectre: - Add entry code register clearing to reduce the Spectre attack surface - Update the Spectre microcode blacklist - Inline the KVM Spectre helpers to get close to v4.14 performance again. - Fix indirect_branch_prediction_barrier() - Fix/improve Spectre related kernel messages - Fix array_index_nospec_mask() asm constraint - KVM: fix two MSR handling bugs PTI: - Fix a paranoid entry PTI CR3 handling bug - Fix comments objtool: - Fix paranoid_entry() frame pointer warning - Annotate WARN()-related UD2 as reachable - Various fixes - Add Add Peter Zijlstra as objtool co-maintainer Misc: - Various x86 entry code self-test fixes - Improve/simplify entry code stack frame generation and handling after recent heavy-handed PTI and Spectre changes. (There's two more WIP improvements expected here.) - Type fix for cache entries There's also some low risk non-fix changes I've included in this branch to reduce backporting conflicts: - rename a confusing x86_cpu field name - de-obfuscate the naming of single-TLB flushing primitives" * 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (41 commits) x86/entry/64: Fix CR3 restore in paranoid_exit() x86/cpu: Change type of x86_cache_size variable to unsigned int x86/spectre: Fix an error message x86/cpu: Rename cpu_data.x86_mask to cpu_data.x86_stepping selftests/x86/mpx: Fix incorrect bounds with old _sigfault x86/mm: Rename flush_tlb_single() and flush_tlb_one() to __flush_tlb_one_[user|kernel]() x86/speculation: Add <asm/msr-index.h> dependency nospec: Move array_index_nospec() parameter checking into separate macro x86/speculation: Fix up array_index_nospec_mask() asm constraint x86/debug: Use UD2 for WARN() x86/debug, objtool: Annotate WARN()-related UD2 as reachable objtool: Fix segfault in ignore_unreachable_insn() selftests/x86: Disable tests requiring 32-bit support on pure 64-bit systems selftests/x86: Do not rely on "int $0x80" in single_step_syscall.c selftests/x86: Do not rely on "int $0x80" in test_mremap_vdso.c selftests/x86: Fix build bug caused by the 5lvl test which has been moved to the VM directory selftests/x86/pkeys: Remove unused functions selftests/x86: Clean up and document sscanf() usage selftests/x86: Fix vDSO selftest segfault for vsyscall=none x86/entry/64: Remove the unused 'icebp' macro ...
2 parents 6556677 + e486575 commit d4667ca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+444
-362
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9946,6 +9946,7 @@ F: drivers/nfc/nxp-nci
99469946

99479947
OBJTOOL
99489948
M: Josh Poimboeuf <[email protected]>
9949+
M: Peter Zijlstra <[email protected]>
99499950
S: Supported
99509951
F: tools/objtool/
99519952

arch/x86/entry/calling.h

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -97,88 +97,77 @@ For 32-bit we have the following conventions - kernel is built with
9797

9898
#define SIZEOF_PTREGS 21*8
9999

100-
.macro ALLOC_PT_GPREGS_ON_STACK
101-
addq $-(15*8), %rsp
102-
.endm
100+
.macro PUSH_AND_CLEAR_REGS rdx=%rdx rax=%rax
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+
*/
108+
pushq %rdi /* pt_regs->di */
109+
pushq %rsi /* pt_regs->si */
110+
pushq \rdx /* pt_regs->dx */
111+
pushq %rcx /* pt_regs->cx */
112+
pushq \rax /* pt_regs->ax */
113+
pushq %r8 /* pt_regs->r8 */
114+
xorq %r8, %r8 /* nospec r8 */
115+
pushq %r9 /* pt_regs->r9 */
116+
xorq %r9, %r9 /* nospec r9 */
117+
pushq %r10 /* pt_regs->r10 */
118+
xorq %r10, %r10 /* nospec r10 */
119+
pushq %r11 /* pt_regs->r11 */
120+
xorq %r11, %r11 /* nospec r11*/
121+
pushq %rbx /* pt_regs->rbx */
122+
xorl %ebx, %ebx /* nospec rbx*/
123+
pushq %rbp /* pt_regs->rbp */
124+
xorl %ebp, %ebp /* nospec rbp*/
125+
pushq %r12 /* pt_regs->r12 */
126+
xorq %r12, %r12 /* nospec r12*/
127+
pushq %r13 /* pt_regs->r13 */
128+
xorq %r13, %r13 /* nospec r13*/
129+
pushq %r14 /* pt_regs->r14 */
130+
xorq %r14, %r14 /* nospec r14*/
131+
pushq %r15 /* pt_regs->r15 */
132+
xorq %r15, %r15 /* nospec r15*/
133+
UNWIND_HINT_REGS
134+
.endm
103135

104-
.macro SAVE_C_REGS_HELPER offset=0 rax=1 rcx=1 r8910=1 r11=1
105-
.if \r11
106-
movq %r11, 6*8+\offset(%rsp)
107-
.endif
108-
.if \r8910
109-
movq %r10, 7*8+\offset(%rsp)
110-
movq %r9, 8*8+\offset(%rsp)
111-
movq %r8, 9*8+\offset(%rsp)
112-
.endif
113-
.if \rax
114-
movq %rax, 10*8+\offset(%rsp)
115-
.endif
116-
.if \rcx
117-
movq %rcx, 11*8+\offset(%rsp)
118-
.endif
119-
movq %rdx, 12*8+\offset(%rsp)
120-
movq %rsi, 13*8+\offset(%rsp)
121-
movq %rdi, 14*8+\offset(%rsp)
122-
UNWIND_HINT_REGS offset=\offset extra=0
123-
.endm
124-
.macro SAVE_C_REGS offset=0
125-
SAVE_C_REGS_HELPER \offset, 1, 1, 1, 1
126-
.endm
127-
.macro SAVE_C_REGS_EXCEPT_RAX_RCX offset=0
128-
SAVE_C_REGS_HELPER \offset, 0, 0, 1, 1
129-
.endm
130-
.macro SAVE_C_REGS_EXCEPT_R891011
131-
SAVE_C_REGS_HELPER 0, 1, 1, 0, 0
132-
.endm
133-
.macro SAVE_C_REGS_EXCEPT_RCX_R891011
134-
SAVE_C_REGS_HELPER 0, 1, 0, 0, 0
135-
.endm
136-
.macro SAVE_C_REGS_EXCEPT_RAX_RCX_R11
137-
SAVE_C_REGS_HELPER 0, 0, 0, 1, 0
138-
.endm
139-
140-
.macro SAVE_EXTRA_REGS offset=0
141-
movq %r15, 0*8+\offset(%rsp)
142-
movq %r14, 1*8+\offset(%rsp)
143-
movq %r13, 2*8+\offset(%rsp)
144-
movq %r12, 3*8+\offset(%rsp)
145-
movq %rbp, 4*8+\offset(%rsp)
146-
movq %rbx, 5*8+\offset(%rsp)
147-
UNWIND_HINT_REGS offset=\offset
148-
.endm
149-
150-
.macro POP_EXTRA_REGS
136+
.macro POP_REGS pop_rdi=1 skip_r11rcx=0
151137
popq %r15
152138
popq %r14
153139
popq %r13
154140
popq %r12
155141
popq %rbp
156142
popq %rbx
157-
.endm
158-
159-
.macro POP_C_REGS
143+
.if \skip_r11rcx
144+
popq %rsi
145+
.else
160146
popq %r11
147+
.endif
161148
popq %r10
162149
popq %r9
163150
popq %r8
164151
popq %rax
152+
.if \skip_r11rcx
153+
popq %rsi
154+
.else
165155
popq %rcx
156+
.endif
166157
popq %rdx
167158
popq %rsi
159+
.if \pop_rdi
168160
popq %rdi
169-
.endm
170-
171-
.macro icebp
172-
.byte 0xf1
173-
.endm
161+
.endif
162+
.endm
174163

175164
/*
176165
* This is a sneaky trick to help the unwinder find pt_regs on the stack. The
177166
* frame pointer is replaced with an encoded pointer to pt_regs. The encoding
178167
* is just setting the LSB, which makes it an invalid stack address and is also
179168
* a signal to the unwinder that it's a pt_regs pointer in disguise.
180169
*
181-
* NOTE: This macro must be used *after* SAVE_EXTRA_REGS because it corrupts
170+
* NOTE: This macro must be used *after* PUSH_AND_CLEAR_REGS because it corrupts
182171
* the original rbp.
183172
*/
184173
.macro ENCODE_FRAME_POINTER ptregs_offset=0

arch/x86/entry/entry_64.S

Lines changed: 19 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ ENTRY(entry_SYSCALL_64)
213213

214214
swapgs
215215
/*
216-
* This path is not taken when PAGE_TABLE_ISOLATION is disabled so it
216+
* This path is only taken when PAGE_TABLE_ISOLATION is disabled so it
217217
* is not required to switch CR3.
218218
*/
219219
movq %rsp, PER_CPU_VAR(rsp_scratch)
@@ -227,22 +227,8 @@ ENTRY(entry_SYSCALL_64)
227227
pushq %rcx /* pt_regs->ip */
228228
GLOBAL(entry_SYSCALL_64_after_hwframe)
229229
pushq %rax /* pt_regs->orig_ax */
230-
pushq %rdi /* pt_regs->di */
231-
pushq %rsi /* pt_regs->si */
232-
pushq %rdx /* pt_regs->dx */
233-
pushq %rcx /* pt_regs->cx */
234-
pushq $-ENOSYS /* pt_regs->ax */
235-
pushq %r8 /* pt_regs->r8 */
236-
pushq %r9 /* pt_regs->r9 */
237-
pushq %r10 /* pt_regs->r10 */
238-
pushq %r11 /* pt_regs->r11 */
239-
pushq %rbx /* pt_regs->rbx */
240-
pushq %rbp /* pt_regs->rbp */
241-
pushq %r12 /* pt_regs->r12 */
242-
pushq %r13 /* pt_regs->r13 */
243-
pushq %r14 /* pt_regs->r14 */
244-
pushq %r15 /* pt_regs->r15 */
245-
UNWIND_HINT_REGS
230+
231+
PUSH_AND_CLEAR_REGS rax=$-ENOSYS
246232

247233
TRACE_IRQS_OFF
248234

@@ -321,15 +307,7 @@ GLOBAL(entry_SYSCALL_64_after_hwframe)
321307
syscall_return_via_sysret:
322308
/* rcx and r11 are already restored (see code above) */
323309
UNWIND_HINT_EMPTY
324-
POP_EXTRA_REGS
325-
popq %rsi /* skip r11 */
326-
popq %r10
327-
popq %r9
328-
popq %r8
329-
popq %rax
330-
popq %rsi /* skip rcx */
331-
popq %rdx
332-
popq %rsi
310+
POP_REGS pop_rdi=0 skip_r11rcx=1
333311

334312
/*
335313
* Now all regs are restored except RSP and RDI.
@@ -559,9 +537,7 @@ END(irq_entries_start)
559537
call switch_to_thread_stack
560538
1:
561539

562-
ALLOC_PT_GPREGS_ON_STACK
563-
SAVE_C_REGS
564-
SAVE_EXTRA_REGS
540+
PUSH_AND_CLEAR_REGS
565541
ENCODE_FRAME_POINTER
566542

567543
testb $3, CS(%rsp)
@@ -622,15 +598,7 @@ GLOBAL(swapgs_restore_regs_and_return_to_usermode)
622598
ud2
623599
1:
624600
#endif
625-
POP_EXTRA_REGS
626-
popq %r11
627-
popq %r10
628-
popq %r9
629-
popq %r8
630-
popq %rax
631-
popq %rcx
632-
popq %rdx
633-
popq %rsi
601+
POP_REGS pop_rdi=0
634602

635603
/*
636604
* The stack is now user RDI, orig_ax, RIP, CS, EFLAGS, RSP, SS.
@@ -688,8 +656,7 @@ GLOBAL(restore_regs_and_return_to_kernel)
688656
ud2
689657
1:
690658
#endif
691-
POP_EXTRA_REGS
692-
POP_C_REGS
659+
POP_REGS
693660
addq $8, %rsp /* skip regs->orig_ax */
694661
/*
695662
* ARCH_HAS_MEMBARRIER_SYNC_CORE rely on IRET core serialization
@@ -908,7 +875,9 @@ ENTRY(\sym)
908875
pushq $-1 /* ORIG_RAX: no syscall to restart */
909876
.endif
910877

911-
ALLOC_PT_GPREGS_ON_STACK
878+
/* Save all registers in pt_regs */
879+
PUSH_AND_CLEAR_REGS
880+
ENCODE_FRAME_POINTER
912881

913882
.if \paranoid < 2
914883
testb $3, CS(%rsp) /* If coming from userspace, switch stacks */
@@ -1121,9 +1090,7 @@ ENTRY(xen_failsafe_callback)
11211090
addq $0x30, %rsp
11221091
UNWIND_HINT_IRET_REGS
11231092
pushq $-1 /* orig_ax = -1 => not a system call */
1124-
ALLOC_PT_GPREGS_ON_STACK
1125-
SAVE_C_REGS
1126-
SAVE_EXTRA_REGS
1093+
PUSH_AND_CLEAR_REGS
11271094
ENCODE_FRAME_POINTER
11281095
jmp error_exit
11291096
END(xen_failsafe_callback)
@@ -1163,16 +1130,13 @@ idtentry machine_check do_mce has_error_code=0 paranoid=1
11631130
#endif
11641131

11651132
/*
1166-
* Save all registers in pt_regs, and switch gs if needed.
1133+
* Switch gs if needed.
11671134
* Use slow, but surefire "are we in kernel?" check.
11681135
* Return: ebx=0: need swapgs on exit, ebx=1: otherwise
11691136
*/
11701137
ENTRY(paranoid_entry)
11711138
UNWIND_HINT_FUNC
11721139
cld
1173-
SAVE_C_REGS 8
1174-
SAVE_EXTRA_REGS 8
1175-
ENCODE_FRAME_POINTER 8
11761140
movl $1, %ebx
11771141
movl $MSR_GS_BASE, %ecx
11781142
rdmsr
@@ -1211,21 +1175,18 @@ ENTRY(paranoid_exit)
12111175
jmp .Lparanoid_exit_restore
12121176
.Lparanoid_exit_no_swapgs:
12131177
TRACE_IRQS_IRETQ_DEBUG
1178+
RESTORE_CR3 scratch_reg=%rbx save_reg=%r14
12141179
.Lparanoid_exit_restore:
12151180
jmp restore_regs_and_return_to_kernel
12161181
END(paranoid_exit)
12171182

12181183
/*
1219-
* Save all registers in pt_regs, and switch gs if needed.
1184+
* Switch gs if needed.
12201185
* Return: EBX=0: came from user mode; EBX=1: otherwise
12211186
*/
12221187
ENTRY(error_entry)
1223-
UNWIND_HINT_FUNC
1188+
UNWIND_HINT_REGS offset=8
12241189
cld
1225-
SAVE_C_REGS 8
1226-
SAVE_EXTRA_REGS 8
1227-
ENCODE_FRAME_POINTER 8
1228-
xorl %ebx, %ebx
12291190
testb $3, CS+8(%rsp)
12301191
jz .Lerror_kernelspace
12311192

@@ -1406,22 +1367,7 @@ ENTRY(nmi)
14061367
pushq 1*8(%rdx) /* pt_regs->rip */
14071368
UNWIND_HINT_IRET_REGS
14081369
pushq $-1 /* pt_regs->orig_ax */
1409-
pushq %rdi /* pt_regs->di */
1410-
pushq %rsi /* pt_regs->si */
1411-
pushq (%rdx) /* pt_regs->dx */
1412-
pushq %rcx /* pt_regs->cx */
1413-
pushq %rax /* pt_regs->ax */
1414-
pushq %r8 /* pt_regs->r8 */
1415-
pushq %r9 /* pt_regs->r9 */
1416-
pushq %r10 /* pt_regs->r10 */
1417-
pushq %r11 /* pt_regs->r11 */
1418-
pushq %rbx /* pt_regs->rbx */
1419-
pushq %rbp /* pt_regs->rbp */
1420-
pushq %r12 /* pt_regs->r12 */
1421-
pushq %r13 /* pt_regs->r13 */
1422-
pushq %r14 /* pt_regs->r14 */
1423-
pushq %r15 /* pt_regs->r15 */
1424-
UNWIND_HINT_REGS
1370+
PUSH_AND_CLEAR_REGS rdx=(%rdx)
14251371
ENCODE_FRAME_POINTER
14261372

14271373
/*
@@ -1631,7 +1577,8 @@ end_repeat_nmi:
16311577
* frame to point back to repeat_nmi.
16321578
*/
16331579
pushq $-1 /* ORIG_RAX: no syscall to restart */
1634-
ALLOC_PT_GPREGS_ON_STACK
1580+
PUSH_AND_CLEAR_REGS
1581+
ENCODE_FRAME_POINTER
16351582

16361583
/*
16371584
* Use paranoid_entry to handle SWAPGS, but no need to use paranoid_exit
@@ -1655,8 +1602,7 @@ end_repeat_nmi:
16551602
nmi_swapgs:
16561603
SWAPGS_UNSAFE_STACK
16571604
nmi_restore:
1658-
POP_EXTRA_REGS
1659-
POP_C_REGS
1605+
POP_REGS
16601606

16611607
/*
16621608
* Skip orig_ax and the "outermost" frame to point RSP at the "iret"

0 commit comments

Comments
 (0)