aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2018-11-25 13:33:55 -0500
committerThomas Gleixner <tglx@linutronix.de>2018-11-28 05:57:14 -0500
commit6b3e64c237c072797a9ec918654a60e3a46488e2 (patch)
tree0ff2bb89748be470b84d29bf74fb34aacf716db0
parent7cc765a67d8e04ef7d772425ca5a2a1e2b894c15 (diff)
x86/speculation: Add seccomp Spectre v2 user space protection mode
If 'prctl' mode of user space protection from spectre v2 is selected on the kernel command-line, STIBP and IBPB are applied on tasks which restrict their indirect branch speculation via prctl. SECCOMP enables the SSBD mitigation for sandboxed tasks already, so it makes sense to prevent spectre v2 user space to user space attacks as well. The Intel mitigation guide documents how STIPB works: Setting bit 1 (STIBP) of the IA32_SPEC_CTRL MSR on a logical processor prevents the predicted targets of indirect branches on any logical processor of that core from being controlled by software that executes (or executed previously) on another logical processor of the same core. Ergo setting STIBP protects the task itself from being attacked from a task running on a different hyper-thread and protects the tasks running on different hyper-threads from being attacked. While the document suggests that the branch predictors are shielded between the logical processors, the observed performance regressions suggest that STIBP simply disables the branch predictor more or less completely. Of course the document wording is vague, but the fact that there is also no requirement for issuing IBPB when STIBP is used points clearly in that direction. The kernel still issues IBPB even when STIBP is used until Intel clarifies the whole mechanism. IBPB is issued when the task switches out, so malicious sandbox code cannot mistrain the branch predictor for the next user space task on the same logical processor. Signed-off-by: Jiri Kosina <jkosina@suse.cz> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Ingo Molnar <mingo@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Tom Lendacky <thomas.lendacky@amd.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: David Woodhouse <dwmw@amazon.co.uk> Cc: Tim Chen <tim.c.chen@linux.intel.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Casey Schaufler <casey.schaufler@intel.com> Cc: Asit Mallick <asit.k.mallick@intel.com> Cc: Arjan van de Ven <arjan@linux.intel.com> Cc: Jon Masters <jcm@redhat.com> Cc: Waiman Long <longman9394@gmail.com> Cc: Greg KH <gregkh@linuxfoundation.org> Cc: Dave Stewart <david.c.stewart@intel.com> Cc: Kees Cook <keescook@chromium.org> Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20181125185006.051663132@linutronix.de
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt9
-rw-r--r--arch/x86/include/asm/nospec-branch.h1
-rw-r--r--arch/x86/kernel/cpu/bugs.c17
3 files changed, 25 insertions, 2 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index a9b98a4e8789..f405281bb202 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4241,9 +4241,16 @@
4241 per thread. The mitigation control state 4241 per thread. The mitigation control state
4242 is inherited on fork. 4242 is inherited on fork.
4243 4243
4244 seccomp
4245 - Same as "prctl" above, but all seccomp
4246 threads will enable the mitigation unless
4247 they explicitly opt out.
4248
4244 auto - Kernel selects the mitigation depending on 4249 auto - Kernel selects the mitigation depending on
4245 the available CPU features and vulnerability. 4250 the available CPU features and vulnerability.
4246 Default is prctl. 4251
4252 Default mitigation:
4253 If CONFIG_SECCOMP=y then "seccomp", otherwise "prctl"
4247 4254
4248 Not specifying this option is equivalent to 4255 Not specifying this option is equivalent to
4249 spectre_v2_user=auto. 4256 spectre_v2_user=auto.
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 2adbe7b047fa..032b6009baab 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -233,6 +233,7 @@ enum spectre_v2_user_mitigation {
233 SPECTRE_V2_USER_NONE, 233 SPECTRE_V2_USER_NONE,
234 SPECTRE_V2_USER_STRICT, 234 SPECTRE_V2_USER_STRICT,
235 SPECTRE_V2_USER_PRCTL, 235 SPECTRE_V2_USER_PRCTL,
236 SPECTRE_V2_USER_SECCOMP,
236}; 237};
237 238
238/* The Speculative Store Bypass disable variants */ 239/* The Speculative Store Bypass disable variants */
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index d0137d10f9a6..c9e304960534 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -256,12 +256,14 @@ enum spectre_v2_user_cmd {
256 SPECTRE_V2_USER_CMD_AUTO, 256 SPECTRE_V2_USER_CMD_AUTO,
257 SPECTRE_V2_USER_CMD_FORCE, 257 SPECTRE_V2_USER_CMD_FORCE,
258 SPECTRE_V2_USER_CMD_PRCTL, 258 SPECTRE_V2_USER_CMD_PRCTL,
259 SPECTRE_V2_USER_CMD_SECCOMP,
259}; 260};
260 261
261static const char * const spectre_v2_user_strings[] = { 262static const char * const spectre_v2_user_strings[] = {
262 [SPECTRE_V2_USER_NONE] = "User space: Vulnerable", 263 [SPECTRE_V2_USER_NONE] = "User space: Vulnerable",
263 [SPECTRE_V2_USER_STRICT] = "User space: Mitigation: STIBP protection", 264 [SPECTRE_V2_USER_STRICT] = "User space: Mitigation: STIBP protection",
264 [SPECTRE_V2_USER_PRCTL] = "User space: Mitigation: STIBP via prctl", 265 [SPECTRE_V2_USER_PRCTL] = "User space: Mitigation: STIBP via prctl",
266 [SPECTRE_V2_USER_SECCOMP] = "User space: Mitigation: STIBP via seccomp and prctl",
265}; 267};
266 268
267static const struct { 269static const struct {
@@ -273,6 +275,7 @@ static const struct {
273 { "off", SPECTRE_V2_USER_CMD_NONE, false }, 275 { "off", SPECTRE_V2_USER_CMD_NONE, false },
274 { "on", SPECTRE_V2_USER_CMD_FORCE, true }, 276 { "on", SPECTRE_V2_USER_CMD_FORCE, true },
275 { "prctl", SPECTRE_V2_USER_CMD_PRCTL, false }, 277 { "prctl", SPECTRE_V2_USER_CMD_PRCTL, false },
278 { "seccomp", SPECTRE_V2_USER_CMD_SECCOMP, false },
276}; 279};
277 280
278static void __init spec_v2_user_print_cond(const char *reason, bool secure) 281static void __init spec_v2_user_print_cond(const char *reason, bool secure)
@@ -332,10 +335,16 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
332 case SPECTRE_V2_USER_CMD_FORCE: 335 case SPECTRE_V2_USER_CMD_FORCE:
333 mode = SPECTRE_V2_USER_STRICT; 336 mode = SPECTRE_V2_USER_STRICT;
334 break; 337 break;
335 case SPECTRE_V2_USER_CMD_AUTO:
336 case SPECTRE_V2_USER_CMD_PRCTL: 338 case SPECTRE_V2_USER_CMD_PRCTL:
337 mode = SPECTRE_V2_USER_PRCTL; 339 mode = SPECTRE_V2_USER_PRCTL;
338 break; 340 break;
341 case SPECTRE_V2_USER_CMD_AUTO:
342 case SPECTRE_V2_USER_CMD_SECCOMP:
343 if (IS_ENABLED(CONFIG_SECCOMP))
344 mode = SPECTRE_V2_USER_SECCOMP;
345 else
346 mode = SPECTRE_V2_USER_PRCTL;
347 break;
339 } 348 }
340 349
341 /* Initialize Indirect Branch Prediction Barrier */ 350 /* Initialize Indirect Branch Prediction Barrier */
@@ -347,6 +356,7 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
347 static_branch_enable(&switch_mm_always_ibpb); 356 static_branch_enable(&switch_mm_always_ibpb);
348 break; 357 break;
349 case SPECTRE_V2_USER_PRCTL: 358 case SPECTRE_V2_USER_PRCTL:
359 case SPECTRE_V2_USER_SECCOMP:
350 static_branch_enable(&switch_mm_cond_ibpb); 360 static_branch_enable(&switch_mm_cond_ibpb);
351 break; 361 break;
352 default: 362 default:
@@ -591,6 +601,7 @@ void arch_smt_update(void)
591 update_stibp_strict(); 601 update_stibp_strict();
592 break; 602 break;
593 case SPECTRE_V2_USER_PRCTL: 603 case SPECTRE_V2_USER_PRCTL:
604 case SPECTRE_V2_USER_SECCOMP:
594 update_indir_branch_cond(); 605 update_indir_branch_cond();
595 break; 606 break;
596 } 607 }
@@ -833,6 +844,8 @@ void arch_seccomp_spec_mitigate(struct task_struct *task)
833{ 844{
834 if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP) 845 if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP)
835 ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE); 846 ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE);
847 if (spectre_v2_user == SPECTRE_V2_USER_SECCOMP)
848 ib_prctl_set(task, PR_SPEC_FORCE_DISABLE);
836} 849}
837#endif 850#endif
838 851
@@ -864,6 +877,7 @@ static int ib_prctl_get(struct task_struct *task)
864 case SPECTRE_V2_USER_NONE: 877 case SPECTRE_V2_USER_NONE:
865 return PR_SPEC_ENABLE; 878 return PR_SPEC_ENABLE;
866 case SPECTRE_V2_USER_PRCTL: 879 case SPECTRE_V2_USER_PRCTL:
880 case SPECTRE_V2_USER_SECCOMP:
867 if (task_spec_ib_force_disable(task)) 881 if (task_spec_ib_force_disable(task))
868 return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; 882 return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
869 if (task_spec_ib_disable(task)) 883 if (task_spec_ib_disable(task))
@@ -1063,6 +1077,7 @@ static char *stibp_state(void)
1063 case SPECTRE_V2_USER_STRICT: 1077 case SPECTRE_V2_USER_STRICT:
1064 return ", STIBP: forced"; 1078 return ", STIBP: forced";
1065 case SPECTRE_V2_USER_PRCTL: 1079 case SPECTRE_V2_USER_PRCTL:
1080 case SPECTRE_V2_USER_SECCOMP:
1066 if (static_key_enabled(&switch_to_cond_stibp)) 1081 if (static_key_enabled(&switch_to_cond_stibp))
1067 return ", STIBP: conditional"; 1082 return ", STIBP: conditional";
1068 } 1083 }