Implement Kernel IBRS - currently the only known option to mitigate RSB underflow speculation issues on Skylake hardware. Note: since IBRS_ENTER requires fuller context established than UNTRAIN_RET, it must be placed after it. However, since UNTRAIN_RET itself implies a RET, it must come after IBRS_ENTER. This means IBRS_ENTER needs to also move UNTRAIN_RET. Note 2: KERNEL_IBRS is sub-optimal for XenPV.
Unified · Split
| @@ -7,6 +7,8 @@ · 6 unmodified lines | ||
| 7 | 7 | #include <asm/asm-offsets.h> |
| 8 | 8 | #include <asm/processor-flags.h> |
| 9 | 9 | #include <asm/ptrace-abi.h> |
| 10 | +#include <asm/msr.h> | |
| 11 | +#include <asm/nospec-branch.h> | |
| 10 | 12 | |
| 11 | 13 | /* |
| 12 | 14 | |
| @@ -282,6 +284,62 @@ For 32-bit we have the following conventions - kernel is built with · 269 unmodified lines | ||
| 282 | 284 | |
| 283 | 285 | #endif |
| 284 | 286 | |
| 287 | +/* | |
| 288 | + * IBRS kernel mitigation for Spectre_v2. | |
| 289 | + * | |
| 290 | + * Assumes full context is established (PUSH_REGS, CR3 and GS) and it clobbers | |
| 291 | + * the regs it uses (AX, CX, DX). Must be called before the first RET | |
| 292 | + * instruction (NOTE! UNTRAIN_RET includes a RET instruction) | |
| 293 | + * | |
| 294 | + * The optional argument is used to save/restore the current value, | |
| 295 | + * which is used on the paranoid paths. | |
| 296 | + * | |
| 297 | + * Assumes x86_spec_ctrl_{base,current} to have SPEC_CTRL_IBRS set. | |
| 298 | + */ | |
| 299 | +.macro IBRS_ENTER save_reg | |
| 300 | + ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS | |
| 301 | + movl $MSR_IA32_SPEC_CTRL, %ecx | |
| 302 | + | |
| 303 | +.ifnb \save_reg | |
| 304 | + rdmsr | |
| 305 | + shl $32, %rdx | |
| 306 | + or %rdx, %rax | |
| 307 | + mov %rax, \save_reg | |
| 308 | + test $SPEC_CTRL_IBRS, %eax | |
| 309 | + jz .Ldo_wrmsr_\@ | |
| 310 | + lfence | |
| 311 | + jmp .Lend_\@ | |
| 312 | +.Ldo_wrmsr_\@: | |
| 313 | +.endif | |
| 314 | + | |
| 315 | + movq PER_CPU_VAR(x86_spec_ctrl_current), %rdx | |
| 316 | + movl %edx, %eax | |
| 317 | + shr $32, %rdx | |
| 318 | + wrmsr | |
| 319 | +.Lend_\@: | |
| 320 | +.endm | |
| 321 | + | |
| 322 | +/* | |
| 323 | + * Similar to IBRS_ENTER, requires KERNEL GS,CR3 and clobbers (AX, CX, DX) | |
| 324 | + * regs. Must be called after the last RET. | |
| 325 | + */ | |
| 326 | +.macro IBRS_EXIT save_reg | |
| 327 | + ALTERNATIVE "jmp .Lend_\@", "", X86_FEATURE_KERNEL_IBRS | |
| 328 | + movl $MSR_IA32_SPEC_CTRL, %ecx | |
| 329 | + | |
| 330 | +.ifnb \save_reg | |
| 331 | + mov \save_reg, %rdx | |
| 332 | +.else | |
| 333 | + movq PER_CPU_VAR(x86_spec_ctrl_current), %rdx | |
| 334 | + andl $(~SPEC_CTRL_IBRS), %edx | |
| 335 | +.endif | |
| 336 | + | |
| 337 | + movl %edx, %eax | |
| 338 | + shr $32, %rdx | |
| 339 | + wrmsr | |
| 340 | +.Lend_\@: | |
| 341 | +.endm | |
| 342 | + | |
| 285 | 343 | /* |
| 286 | 344 | * Mitigate Spectre v1 for conditional swapgs code paths. |
| 287 | 345 | * |
| @@ -96,7 +96,6 @@ SYM_CODE_START(entry_SYSCALL_64) · 95 unmodified lines | ||
| 96 | 96 | |
| 97 | 97 | SYM_INNER_LABEL(entry_SYSCALL_64_safe_stack, SYM_L_GLOBAL) |
| 98 | 98 | ANNOTATE_NOENDBR |
| 99 | − UNTRAIN_RET | |
| 100 | 99 | |
| 101 | 100 | /* Construct struct pt_regs on stack */ |
| 102 | 101 | pushq $__USER_DS /* pt_regs->ss */ |
| @@ -113,6 +112,11 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL) · 10 unmodified lines | ||
| 113 | 112 | movq %rsp, %rdi |
| 114 | 113 | /* Sign extend the lower 32bit as syscall numbers are treated as int */ |
| 115 | 114 | movslq %eax, %rsi |
| 115 | + | |
| 116 | + /* clobbers %rax, make sure it is after saving the syscall nr */ | |
| 117 | + IBRS_ENTER | |
| 118 | + UNTRAIN_RET | |
| 119 | + | |
| 116 | 120 | call do_syscall_64 /* returns with IRQs disabled */ |
| 117 | 121 | |
| 118 | 122 | /* |
| @@ -192,6 +196,7 @@ SYM_INNER_LABEL(entry_SYSCALL_64_after_hwframe, SYM_L_GLOBAL) · 73 unmodified lines | ||
| 192 | 196 | * perf profiles. Nothing jumps here. |
| 193 | 197 | */ |
| 194 | 198 | syscall_return_via_sysret: |
| 199 | + IBRS_EXIT | |
| 195 | 200 | POP_REGS pop_rdi=0 |
| 196 | 201 | |
| 197 | 202 | /* |
| @@ -605,6 +610,7 @@ __irqentry_text_end: · 407 unmodified lines | ||
| 605 | 610 | |
| 606 | 611 | SYM_CODE_START_LOCAL(common_interrupt_return) |
| 607 | 612 | SYM_INNER_LABEL(swapgs_restore_regs_and_return_to_usermode, SYM_L_GLOBAL) |
| 613 | + IBRS_EXIT | |
| 608 | 614 | #ifdef CONFIG_DEBUG_ENTRY |
| 609 | 615 | /* Assert that pt_regs indicates user mode. */ |
| 610 | 616 | testb $3, CS(%rsp) |
| @@ -891,6 +897,9 @@ SYM_CODE_END(xen_failsafe_callback) · 280 unmodified lines | ||
| 891 | 897 | * 1 -> no SWAPGS on exit |
| 892 | 898 | * |
| 893 | 899 | * Y GSBASE value at entry, must be restored in paranoid_exit |
| 900 | + * | |
| 901 | + * R14 - old CR3 | |
| 902 | + * R15 - old SPEC_CTRL | |
| 894 | 903 | */ |
| 895 | 904 | SYM_CODE_START_LOCAL(paranoid_entry) |
| 896 | 905 | UNWIND_HINT_FUNC |
| @@ -913,7 +922,6 @@ SYM_CODE_START_LOCAL(paranoid_entry) · 16 unmodified lines | ||
| 913 | 922 | * be retrieved from a kernel internal table. |
| 914 | 923 | */ |
| 915 | 924 | SAVE_AND_SWITCH_TO_KERNEL_CR3 scratch_reg=%rax save_reg=%r14 |
| 916 | − UNTRAIN_RET | |
| 917 | 925 | |
| 918 | 926 | /* |
| 919 | 927 | * Handling GSBASE depends on the availability of FSGSBASE. |
| @@ -935,7 +943,7 @@ SYM_CODE_START_LOCAL(paranoid_entry) · 15 unmodified lines | ||
| 935 | 943 | * is needed here. |
| 936 | 944 | */ |
| 937 | 945 | SAVE_AND_SET_GSBASE scratch_reg=%rax save_reg=%rbx |
| 938 | − RET | |
| 946 | + jmp .Lparanoid_gsbase_done | |
| 939 | 947 | |
| 940 | 948 | .Lparanoid_entry_checkgs: |
| 941 | 949 | /* EBX = 1 -> kernel GSBASE active, no restore required */ |
| @@ -954,8 +962,16 @@ SYM_CODE_START_LOCAL(paranoid_entry) · 12 unmodified lines | ||
| 954 | 962 | xorl %ebx, %ebx |
| 955 | 963 | swapgs |
| 956 | 964 | .Lparanoid_kernel_gsbase: |
| 957 | − | |
| 958 | 965 | FENCE_SWAPGS_KERNEL_ENTRY |
| 966 | +.Lparanoid_gsbase_done: | |
| 967 | + | |
| 968 | + /* | |
| 969 | + * Once we have CR3 and %GS setup save and set SPEC_CTRL. Just like | |
| 970 | + * CR3 above, keep the old value in a callee saved register. | |
| 971 | + */ | |
| 972 | + IBRS_ENTER save_reg=%r15 | |
| 973 | + UNTRAIN_RET | |
| 974 | + | |
| 959 | 975 | RET |
| 960 | 976 | SYM_CODE_END(paranoid_entry) |
| 961 | 977 | |
| @@ -977,9 +993,19 @@ SYM_CODE_END(paranoid_entry) · 15 unmodified lines | ||
| 977 | 993 | * 1 -> no SWAPGS on exit |
| 978 | 994 | * |
| 979 | 995 | * Y User space GSBASE, must be restored unconditionally |
| 996 | + * | |
| 997 | + * R14 - old CR3 | |
| 998 | + * R15 - old SPEC_CTRL | |
| 980 | 999 | */ |
| 981 | 1000 | SYM_CODE_START_LOCAL(paranoid_exit) |
| 982 | 1001 | UNWIND_HINT_REGS |
| 1002 | + | |
| 1003 | + /* | |
| 1004 | + * Must restore IBRS state before both CR3 and %GS since we need access | |
| 1005 | + * to the per-CPU x86_spec_ctrl_shadow variable. | |
| 1006 | + */ | |
| 1007 | + IBRS_EXIT save_reg=%r15 | |
| 1008 | + | |
| 983 | 1009 | /* |
| 984 | 1010 | * The order of operations is important. RESTORE_CR3 requires |
| 985 | 1011 | * kernel GSBASE. |
| @@ -1023,10 +1049,12 @@ SYM_CODE_START_LOCAL(error_entry) · 37 unmodified lines | ||
| 1023 | 1049 | FENCE_SWAPGS_USER_ENTRY |
| 1024 | 1050 | /* We have user CR3. Change to kernel CR3. */ |
| 1025 | 1051 | SWITCH_TO_KERNEL_CR3 scratch_reg=%rax |
| 1052 | + IBRS_ENTER | |
| 1026 | 1053 | UNTRAIN_RET |
| 1027 | 1054 | |
| 1028 | 1055 | leaq 8(%rsp), %rdi /* arg0 = pt_regs pointer */ |
| 1029 | 1056 | .Lerror_entry_from_usermode_after_swapgs: |
| 1057 | + | |
| 1030 | 1058 | /* Put us onto the real thread stack. */ |
| 1031 | 1059 | call sync_regs |
| 1032 | 1060 | RET |
| @@ -1076,6 +1104,7 @@ SYM_CODE_START_LOCAL(error_entry) · 43 unmodified lines | ||
| 1076 | 1104 | swapgs |
| 1077 | 1105 | FENCE_SWAPGS_USER_ENTRY |
| 1078 | 1106 | SWITCH_TO_KERNEL_CR3 scratch_reg=%rax |
| 1107 | + IBRS_ENTER | |
| 1079 | 1108 | UNTRAIN_RET |
| 1080 | 1109 | |
| 1081 | 1110 | /* |
| @@ -1172,7 +1201,6 @@ SYM_CODE_START(asm_exc_nmi) · 90 unmodified lines | ||
| 1172 | 1201 | movq %rsp, %rdx |
| 1173 | 1202 | movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp |
| 1174 | 1203 | UNWIND_HINT_IRET_REGS base=%rdx offset=8 |
| 1175 | − UNTRAIN_RET | |
| 1176 | 1204 | pushq 5*8(%rdx) /* pt_regs->ss */ |
| 1177 | 1205 | pushq 4*8(%rdx) /* pt_regs->rsp */ |
| 1178 | 1206 | pushq 3*8(%rdx) /* pt_regs->flags */ |
| @@ -1183,6 +1211,9 @@ SYM_CODE_START(asm_exc_nmi) · 4 unmodified lines | ||
| 1183 | 1211 | PUSH_AND_CLEAR_REGS rdx=(%rdx) |
| 1184 | 1212 | ENCODE_FRAME_POINTER |
| 1185 | 1213 | |
| 1214 | + IBRS_ENTER | |
| 1215 | + UNTRAIN_RET | |
| 1216 | + | |
| 1186 | 1217 | /* |
| 1187 | 1218 | * At this point we no longer need to worry about stack damage |
| 1188 | 1219 | * due to nesting -- we're on the normal thread stack and we're |
| @@ -1407,6 +1438,9 @@ end_repeat_nmi: · 218 unmodified lines | ||
| 1407 | 1438 | movq $-1, %rsi |
| 1408 | 1439 | call exc_nmi |
| 1409 | 1440 | |
| 1441 | + /* Always restore stashed SPEC_CTRL value (see paranoid_entry) */ | |
| 1442 | + IBRS_EXIT save_reg=%r15 | |
| 1443 | + | |
| 1410 | 1444 | /* Always restore stashed CR3 value (see paranoid_entry) */ |
| 1411 | 1445 | RESTORE_CR3 scratch_reg=%r15 save_reg=%r14 |
| 1412 | 1446 | |
| @@ -4,7 +4,6 @@ · 3 unmodified lines | ||
| 4 | 4 | * |
| 5 | 5 | * Copyright 2000-2002 Andi Kleen, SuSE Labs. |
| 6 | 6 | */ |
| 7 | −#include "calling.h" | |
| 8 | 7 | #include <asm/asm-offsets.h> |
| 9 | 8 | #include <asm/current.h> |
| 10 | 9 | #include <asm/errno.h> |
| @@ -18,6 +17,8 @@ · 7 unmodified lines | ||
| 18 | 17 | #include <linux/linkage.h> |
| 19 | 18 | #include <linux/err.h> |
| 20 | 19 | |
| 20 | +#include "calling.h" | |
| 21 | + | |
| 21 | 22 | .section .entry.text, "ax" |
| 22 | 23 | |
| 23 | 24 | /* |
| @@ -73,7 +74,6 @@ SYM_CODE_START(entry_SYSENTER_compat) · 49 unmodified lines | ||
| 73 | 74 | pushq $__USER32_CS /* pt_regs->cs */ |
| 74 | 75 | pushq $0 /* pt_regs->ip = 0 (placeholder) */ |
| 75 | 76 | SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL) |
| 76 | − UNTRAIN_RET | |
| 77 | 77 | |
| 78 | 78 | /* |
| 79 | 79 | * User tracing code (ptrace or signal handlers) might assume that |
| @@ -90,6 +90,9 @@ SYM_INNER_LABEL(entry_SYSENTER_compat_after_hwframe, SYM_L_GLOBAL) · 10 unmodified lines | ||
| 90 | 90 | |
| 91 | 91 | cld |
| 92 | 92 | |
| 93 | + IBRS_ENTER | |
| 94 | + UNTRAIN_RET | |
| 95 | + | |
| 93 | 96 | /* |
| 94 | 97 | * SYSENTER doesn't filter flags, so we need to clear NT and AC |
| 95 | 98 | * ourselves. To save a few cycles, we can check whether |
| @@ -192,7 +195,6 @@ SYM_CODE_START(entry_SYSCALL_compat) · 96 unmodified lines | ||
| 192 | 195 | |
| 193 | 196 | SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL) |
| 194 | 197 | ANNOTATE_NOENDBR |
| 195 | − UNTRAIN_RET | |
| 196 | 198 | |
| 197 | 199 | /* Construct struct pt_regs on stack */ |
| 198 | 200 | pushq $__USER32_DS /* pt_regs->ss */ |
| @@ -206,6 +208,9 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_after_hwframe, SYM_L_GLOBAL) · 7 unmodified lines | ||
| 206 | 208 | PUSH_AND_CLEAR_REGS rcx=%rbp rax=$-ENOSYS |
| 207 | 209 | UNWIND_HINT_REGS |
| 208 | 210 | |
| 211 | + IBRS_ENTER | |
| 212 | + UNTRAIN_RET | |
| 213 | + | |
| 209 | 214 | movq %rsp, %rdi |
| 210 | 215 | call do_fast_syscall_32 |
| 211 | 216 | /* XEN PV guests always use IRET path */ |
| @@ -220,6 +225,8 @@ sysret32_from_system_call: · 8 unmodified lines | ||
| 220 | 225 | */ |
| 221 | 226 | STACKLEAK_ERASE |
| 222 | 227 | |
| 228 | + IBRS_EXIT | |
| 229 | + | |
| 223 | 230 | movq RBX(%rsp), %rbx /* pt_regs->rbx */ |
| 224 | 231 | movq RBP(%rsp), %rbp /* pt_regs->rbp */ |
| 225 | 232 | movq EFLAGS(%rsp), %r11 /* pt_regs->flags (in r11) */ |
| @@ -335,12 +342,14 @@ SYM_CODE_START(entry_INT80_compat) · 109 unmodified lines | ||
| 335 | 342 | pushq 0*8(%rax) /* regs->orig_ax */ |
| 336 | 343 | .Lint80_keep_stack: |
| 337 | 344 | |
| 338 | − UNTRAIN_RET | |
| 339 | 345 | PUSH_AND_CLEAR_REGS rax=$-ENOSYS |
| 340 | 346 | UNWIND_HINT_REGS |
| 341 | 347 | |
| 342 | 348 | cld |
| 343 | 349 | |
| 350 | + IBRS_ENTER | |
| 351 | + UNTRAIN_RET | |
| 352 | + | |
| 344 | 353 | movq %rsp, %rdi |
| 345 | 354 | call do_int80_syscall_32 |
| 346 | 355 | jmp swapgs_restore_regs_and_return_to_usermode |
| @@ -203,7 +203,7 @@ · 202 unmodified lines | ||
| 203 | 203 | #define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */ |
| 204 | 204 | #define X86_FEATURE_XCOMPACTED ( 7*32+10) /* "" Use compacted XSTATE (XSAVES or XSAVEC) */ |
| 205 | 205 | #define X86_FEATURE_PTI ( 7*32+11) /* Kernel Page Table Isolation enabled */ |
| 206 | −/* FREE! ( 7*32+12) */ | |
| 206 | +#define X86_FEATURE_KERNEL_IBRS ( 7*32+12) /* "" Set/clear IBRS on kernel entry/exit */ | |
| 207 | 207 | /* FREE! ( 7*32+13) */ |
| 208 | 208 | #define X86_FEATURE_INTEL_PPIN ( 7*32+14) /* Intel Processor Inventory Number */ |
| 209 | 209 | #define X86_FEATURE_CDP_L2 ( 7*32+15) /* Code and Data Prioritization L2 */ |