aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Poimboeuf <jpoimboe@redhat.com>2019-07-08 12:52:25 -0400
committerThomas Gleixner <tglx@linutronix.de>2019-07-09 08:11:45 -0400
commit18ec54fdd6d18d92025af097cd042a75cf0ea24c (patch)
tree9ccf221766201a590ad9e331570ba78162aeaf21
parent222a21d29521d144f3dd7a0bc4d4020e448f0126 (diff)
x86/speculation: Prepare entry code for Spectre v1 swapgs mitigations
Spectre v1 isn't only about array bounds checks. It can affect any conditional checks. The kernel entry code interrupt, exception, and NMI handlers all have conditional swapgs checks. Those may be problematic in the context of Spectre v1, as kernel code can speculatively run with a user GS. For example: if (coming from user space) swapgs mov %gs:<percpu_offset>, %reg mov (%reg), %reg1 When coming from user space, the CPU can speculatively skip the swapgs, and then do a speculative percpu load using the user GS value. So the user can speculatively force a read of any kernel value. If a gadget exists which uses the percpu value as an address in another load/store, then the contents of the kernel value may become visible via an L1 side channel attack. A similar attack exists when coming from kernel space. The CPU can speculatively do the swapgs, causing the user GS to get used for the rest of the speculative window. The mitigation is similar to a traditional Spectre v1 mitigation, except: a) index masking isn't possible; because the index (percpu offset) isn't user-controlled; and b) an lfence is needed in both the "from user" swapgs path and the "from kernel" non-swapgs path (because of the two attacks described above). The user entry swapgs paths already have SWITCH_TO_KERNEL_CR3, which has a CR3 write when PTI is enabled. Since CR3 writes are serializing, the lfences can be skipped in those cases. On the other hand, the kernel entry swapgs paths don't depend on PTI. To avoid unnecessary lfences for the user entry case, create two separate features for alternative patching: X86_FEATURE_FENCE_SWAPGS_USER X86_FEATURE_FENCE_SWAPGS_KERNEL Use these features in entry code to patch in lfences where needed. The features aren't enabled yet, so there's no functional change. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Dave Hansen <dave.hansen@intel.com>
-rw-r--r--arch/x86/entry/calling.h17
-rw-r--r--arch/x86/entry/entry_64.S21
-rw-r--r--arch/x86/include/asm/cpufeatures.h2
3 files changed, 37 insertions, 3 deletions
diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h
index 9f1f9e3b8230..7ce7ac9d9d3f 100644
--- a/arch/x86/entry/calling.h
+++ b/arch/x86/entry/calling.h
@@ -314,6 +314,23 @@ For 32-bit we have the following conventions - kernel is built with
314 314
315#endif 315#endif
316 316
317/*
318 * Mitigate Spectre v1 for conditional swapgs code paths.
319 *
320 * FENCE_SWAPGS_USER_ENTRY is used in the user entry swapgs code path, to
321 * prevent a speculative swapgs when coming from kernel space.
322 *
323 * FENCE_SWAPGS_KERNEL_ENTRY is used in the kernel entry non-swapgs code path,
324 * to prevent the swapgs from getting speculatively skipped when coming from
325 * user space.
326 */
327.macro FENCE_SWAPGS_USER_ENTRY
328 ALTERNATIVE "", "lfence", X86_FEATURE_FENCE_SWAPGS_USER
329.endm
330.macro FENCE_SWAPGS_KERNEL_ENTRY
331 ALTERNATIVE "", "lfence", X86_FEATURE_FENCE_SWAPGS_KERNEL
332.endm
333
317.macro STACKLEAK_ERASE_NOCLOBBER 334.macro STACKLEAK_ERASE_NOCLOBBER
318#ifdef CONFIG_GCC_PLUGIN_STACKLEAK 335#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
319 PUSH_AND_CLEAR_REGS 336 PUSH_AND_CLEAR_REGS
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index a829dd3117d0..57a0d96d6beb 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -519,7 +519,7 @@ ENTRY(interrupt_entry)
519 testb $3, CS-ORIG_RAX+8(%rsp) 519 testb $3, CS-ORIG_RAX+8(%rsp)
520 jz 1f 520 jz 1f
521 SWAPGS 521 SWAPGS
522 522 FENCE_SWAPGS_USER_ENTRY
523 /* 523 /*
524 * Switch to the thread stack. The IRET frame and orig_ax are 524 * Switch to the thread stack. The IRET frame and orig_ax are
525 * on the stack, as well as the return address. RDI..R12 are 525 * on the stack, as well as the return address. RDI..R12 are
@@ -549,8 +549,10 @@ ENTRY(interrupt_entry)
549 UNWIND_HINT_FUNC 549 UNWIND_HINT_FUNC
550 550
551 movq (%rdi), %rdi 551 movq (%rdi), %rdi
552 jmpq 2f
5521: 5531:
553 554 FENCE_SWAPGS_KERNEL_ENTRY
5552:
554 PUSH_AND_CLEAR_REGS save_ret=1 556 PUSH_AND_CLEAR_REGS save_ret=1
555 ENCODE_FRAME_POINTER 8 557 ENCODE_FRAME_POINTER 8
556 558
@@ -1221,6 +1223,13 @@ ENTRY(paranoid_entry)
1221 */ 1223 */
1222 SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14 1224 SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14
1223 1225
1226 /*
1227 * The above SAVE_AND_SWITCH_TO_KERNEL_CR3 macro doesn't do an
1228 * unconditional CR3 write, even in the PTI case. So do an lfence
1229 * to prevent GS speculation, regardless of whether PTI is enabled.
1230 */
1231 FENCE_SWAPGS_KERNEL_ENTRY
1232
1224 ret 1233 ret
1225END(paranoid_entry) 1234END(paranoid_entry)
1226 1235
@@ -1271,6 +1280,7 @@ ENTRY(error_entry)
1271 * from user mode due to an IRET fault. 1280 * from user mode due to an IRET fault.
1272 */ 1281 */
1273 SWAPGS 1282 SWAPGS
1283 FENCE_SWAPGS_USER_ENTRY
1274 /* We have user CR3. Change to kernel CR3. */ 1284 /* We have user CR3. Change to kernel CR3. */
1275 SWITCH_TO_KERNEL_CR3 scratch_reg=%rax 1285 SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
1276 1286
@@ -1292,6 +1302,8 @@ ENTRY(error_entry)
1292 CALL_enter_from_user_mode 1302 CALL_enter_from_user_mode
1293 ret 1303 ret
1294 1304
1305.Lerror_entry_done_lfence:
1306 FENCE_SWAPGS_KERNEL_ENTRY
1295.Lerror_entry_done: 1307.Lerror_entry_done:
1296 TRACE_IRQS_OFF 1308 TRACE_IRQS_OFF
1297 ret 1309 ret
@@ -1310,7 +1322,7 @@ ENTRY(error_entry)
1310 cmpq %rax, RIP+8(%rsp) 1322 cmpq %rax, RIP+8(%rsp)
1311 je .Lbstep_iret 1323 je .Lbstep_iret
1312 cmpq $.Lgs_change, RIP+8(%rsp) 1324 cmpq $.Lgs_change, RIP+8(%rsp)
1313 jne .Lerror_entry_done 1325 jne .Lerror_entry_done_lfence
1314 1326
1315 /* 1327 /*
1316 * hack: .Lgs_change can fail with user gsbase. If this happens, fix up 1328 * hack: .Lgs_change can fail with user gsbase. If this happens, fix up
@@ -1318,6 +1330,7 @@ ENTRY(error_entry)
1318 * .Lgs_change's error handler with kernel gsbase. 1330 * .Lgs_change's error handler with kernel gsbase.
1319 */ 1331 */
1320 SWAPGS 1332 SWAPGS
1333 FENCE_SWAPGS_USER_ENTRY
1321 SWITCH_TO_KERNEL_CR3 scratch_reg=%rax 1334 SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
1322 jmp .Lerror_entry_done 1335 jmp .Lerror_entry_done
1323 1336
@@ -1332,6 +1345,7 @@ ENTRY(error_entry)
1332 * gsbase and CR3. Switch to kernel gsbase and CR3: 1345 * gsbase and CR3. Switch to kernel gsbase and CR3:
1333 */ 1346 */
1334 SWAPGS 1347 SWAPGS
1348 FENCE_SWAPGS_USER_ENTRY
1335 SWITCH_TO_KERNEL_CR3 scratch_reg=%rax 1349 SWITCH_TO_KERNEL_CR3 scratch_reg=%rax
1336 1350
1337 /* 1351 /*
@@ -1423,6 +1437,7 @@ ENTRY(nmi)
1423 1437
1424 swapgs 1438 swapgs
1425 cld 1439 cld
1440 FENCE_SWAPGS_USER_ENTRY
1426 SWITCH_TO_KERNEL_CR3 scratch_reg=%rdx 1441 SWITCH_TO_KERNEL_CR3 scratch_reg=%rdx
1427 movq %rsp, %rdx 1442 movq %rsp, %rdx
1428 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp 1443 movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 998c2cc08363..4393278666d9 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -281,6 +281,8 @@
281#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* LLC occupancy monitoring */ 281#define X86_FEATURE_CQM_OCCUP_LLC (11*32+ 1) /* LLC occupancy monitoring */
282#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* LLC Total MBM monitoring */ 282#define X86_FEATURE_CQM_MBM_TOTAL (11*32+ 2) /* LLC Total MBM monitoring */
283#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */ 283#define X86_FEATURE_CQM_MBM_LOCAL (11*32+ 3) /* LLC Local MBM monitoring */
284#define X86_FEATURE_FENCE_SWAPGS_USER (11*32+ 4) /* "" LFENCE in user entry SWAPGS path */
285#define X86_FEATURE_FENCE_SWAPGS_KERNEL (11*32+ 5) /* "" LFENCE in kernel entry SWAPGS path */
284 286
285/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ 287/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
286#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */ 288#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* AVX512 BFLOAT16 instructions */