aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2018-04-29 09:26:40 -0400
committerThomas Gleixner <tglx@linutronix.de>2018-05-03 07:55:51 -0400
commita73ec77ee17ec556fe7f165d00314cb7c047b1ac (patch)
treefc626ec0298a4d788dbd8705aacfdce3e3e68bcc
parent885f82bfbc6fefb6664ea27965c3ab9ac4194b8c (diff)
x86/speculation: Add prctl for Speculative Store Bypass mitigation
Add prctl based control for Speculative Store Bypass mitigation and make it the default mitigation for Intel and AMD. Andi Kleen provided the following rationale (slightly redacted): There are multiple levels of impact of Speculative Store Bypass: 1) JITed sandbox. It cannot invoke system calls, but can do PRIME+PROBE and may have call interfaces to other code 2) Native code process. No protection inside the process at this level. 3) Kernel. 4) Between processes. The prctl tries to protect against case (1) doing attacks. If the untrusted code can do random system calls then control is already lost in a much worse way. So there needs to be system call protection in some way (using a JIT not allowing them or seccomp). Or rather if the process can subvert its environment somehow to do the prctl it can already execute arbitrary code, which is much worse than SSB. To put it differently, the point of the prctl is to not allow JITed code to read data it shouldn't read from its JITed sandbox. If it already has escaped its sandbox then it can already read everything it wants in its address space, and do much worse. The ability to control Speculative Store Bypass allows to enable the protection selectively without affecting overall system performance. Based on an initial patch from Tim Chen. Completely rewritten. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt6
-rw-r--r--arch/x86/include/asm/nospec-branch.h1
-rw-r--r--arch/x86/kernel/cpu/bugs.c83
3 files changed, 79 insertions, 11 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index f32112c55f7e..a8d2ae1e335b 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4053,7 +4053,11 @@
4053 off - Unconditionally enable Speculative Store Bypass 4053 off - Unconditionally enable Speculative Store Bypass
4054 auto - Kernel detects whether the CPU model contains an 4054 auto - Kernel detects whether the CPU model contains an
4055 implementation of Speculative Store Bypass and 4055 implementation of Speculative Store Bypass and
4056 picks the most appropriate mitigation 4056 picks the most appropriate mitigation.
4057 prctl - Control Speculative Store Bypass per thread
4058 via prctl. Speculative Store Bypass is enabled
4059 for a process by default. The state of the control
4060 is inherited on fork.
4057 4061
4058 Not specifying this option is equivalent to 4062 Not specifying this option is equivalent to
4059 spec_store_bypass_disable=auto. 4063 spec_store_bypass_disable=auto.
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 1119f14bc883..71ad01422655 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -232,6 +232,7 @@ extern u64 x86_spec_ctrl_get_default(void);
232enum ssb_mitigation { 232enum ssb_mitigation {
233 SPEC_STORE_BYPASS_NONE, 233 SPEC_STORE_BYPASS_NONE,
234 SPEC_STORE_BYPASS_DISABLE, 234 SPEC_STORE_BYPASS_DISABLE,
235 SPEC_STORE_BYPASS_PRCTL,
235}; 236};
236 237
237extern char __indirect_thunk_start[]; 238extern char __indirect_thunk_start[];
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 2bc109d0f8ae..fc9187b6fae7 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -12,6 +12,8 @@
12#include <linux/utsname.h> 12#include <linux/utsname.h>
13#include <linux/cpu.h> 13#include <linux/cpu.h>
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/nospec.h>
16#include <linux/prctl.h>
15 17
16#include <asm/spec-ctrl.h> 18#include <asm/spec-ctrl.h>
17#include <asm/cmdline.h> 19#include <asm/cmdline.h>
@@ -412,20 +414,23 @@ enum ssb_mitigation_cmd {
412 SPEC_STORE_BYPASS_CMD_NONE, 414 SPEC_STORE_BYPASS_CMD_NONE,
413 SPEC_STORE_BYPASS_CMD_AUTO, 415 SPEC_STORE_BYPASS_CMD_AUTO,
414 SPEC_STORE_BYPASS_CMD_ON, 416 SPEC_STORE_BYPASS_CMD_ON,
417 SPEC_STORE_BYPASS_CMD_PRCTL,
415}; 418};
416 419
417static const char *ssb_strings[] = { 420static const char *ssb_strings[] = {
418 [SPEC_STORE_BYPASS_NONE] = "Vulnerable", 421 [SPEC_STORE_BYPASS_NONE] = "Vulnerable",
419 [SPEC_STORE_BYPASS_DISABLE] = "Mitigation: Speculative Store Bypass disabled" 422 [SPEC_STORE_BYPASS_DISABLE] = "Mitigation: Speculative Store Bypass disabled",
423 [SPEC_STORE_BYPASS_PRCTL] = "Mitigation: Speculative Store Bypass disabled via prctl"
420}; 424};
421 425
422static const struct { 426static const struct {
423 const char *option; 427 const char *option;
424 enum ssb_mitigation_cmd cmd; 428 enum ssb_mitigation_cmd cmd;
425} ssb_mitigation_options[] = { 429} ssb_mitigation_options[] = {
426 { "auto", SPEC_STORE_BYPASS_CMD_AUTO }, /* Platform decides */ 430 { "auto", SPEC_STORE_BYPASS_CMD_AUTO }, /* Platform decides */
427 { "on", SPEC_STORE_BYPASS_CMD_ON }, /* Disable Speculative Store Bypass */ 431 { "on", SPEC_STORE_BYPASS_CMD_ON }, /* Disable Speculative Store Bypass */
428 { "off", SPEC_STORE_BYPASS_CMD_NONE }, /* Don't touch Speculative Store Bypass */ 432 { "off", SPEC_STORE_BYPASS_CMD_NONE }, /* Don't touch Speculative Store Bypass */
433 { "prctl", SPEC_STORE_BYPASS_CMD_PRCTL }, /* Disable Speculative Store Bypass via prctl */
429}; 434};
430 435
431static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void) 436static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
@@ -475,14 +480,15 @@ static enum ssb_mitigation_cmd __init __ssb_select_mitigation(void)
475 480
476 switch (cmd) { 481 switch (cmd) {
477 case SPEC_STORE_BYPASS_CMD_AUTO: 482 case SPEC_STORE_BYPASS_CMD_AUTO:
478 /* 483 /* Choose prctl as the default mode */
479 * AMD platforms by default don't need SSB mitigation. 484 mode = SPEC_STORE_BYPASS_PRCTL;
480 */ 485 break;
481 if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
482 break;
483 case SPEC_STORE_BYPASS_CMD_ON: 486 case SPEC_STORE_BYPASS_CMD_ON:
484 mode = SPEC_STORE_BYPASS_DISABLE; 487 mode = SPEC_STORE_BYPASS_DISABLE;
485 break; 488 break;
489 case SPEC_STORE_BYPASS_CMD_PRCTL:
490 mode = SPEC_STORE_BYPASS_PRCTL;
491 break;
486 case SPEC_STORE_BYPASS_CMD_NONE: 492 case SPEC_STORE_BYPASS_CMD_NONE:
487 break; 493 break;
488 } 494 }
@@ -493,7 +499,7 @@ static enum ssb_mitigation_cmd __init __ssb_select_mitigation(void)
493 * - X86_FEATURE_RDS - CPU is able to turn off speculative store bypass 499 * - X86_FEATURE_RDS - CPU is able to turn off speculative store bypass
494 * - X86_FEATURE_SPEC_STORE_BYPASS_DISABLE - engage the mitigation 500 * - X86_FEATURE_SPEC_STORE_BYPASS_DISABLE - engage the mitigation
495 */ 501 */
496 if (mode != SPEC_STORE_BYPASS_NONE) { 502 if (mode == SPEC_STORE_BYPASS_DISABLE) {
497 setup_force_cpu_cap(X86_FEATURE_SPEC_STORE_BYPASS_DISABLE); 503 setup_force_cpu_cap(X86_FEATURE_SPEC_STORE_BYPASS_DISABLE);
498 /* 504 /*
499 * Intel uses the SPEC CTRL MSR Bit(2) for this, while AMD uses 505 * Intel uses the SPEC CTRL MSR Bit(2) for this, while AMD uses
@@ -524,6 +530,63 @@ static void ssb_select_mitigation()
524 530
525#undef pr_fmt 531#undef pr_fmt
526 532
533static int ssb_prctl_set(unsigned long ctrl)
534{
535 bool rds = !!test_tsk_thread_flag(current, TIF_RDS);
536
537 if (ssb_mode != SPEC_STORE_BYPASS_PRCTL)
538 return -ENXIO;
539
540 if (ctrl == PR_SPEC_ENABLE)
541 clear_tsk_thread_flag(current, TIF_RDS);
542 else
543 set_tsk_thread_flag(current, TIF_RDS);
544
545 if (rds != !!test_tsk_thread_flag(current, TIF_RDS))
546 speculative_store_bypass_update();
547
548 return 0;
549}
550
551static int ssb_prctl_get(void)
552{
553 switch (ssb_mode) {
554 case SPEC_STORE_BYPASS_DISABLE:
555 return PR_SPEC_DISABLE;
556 case SPEC_STORE_BYPASS_PRCTL:
557 if (test_tsk_thread_flag(current, TIF_RDS))
558 return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
559 return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
560 default:
561 if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
562 return PR_SPEC_ENABLE;
563 return PR_SPEC_NOT_AFFECTED;
564 }
565}
566
567int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
568{
569 if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE)
570 return -ERANGE;
571
572 switch (which) {
573 case PR_SPEC_STORE_BYPASS:
574 return ssb_prctl_set(ctrl);
575 default:
576 return -ENODEV;
577 }
578}
579
580int arch_prctl_spec_ctrl_get(unsigned long which)
581{
582 switch (which) {
583 case PR_SPEC_STORE_BYPASS:
584 return ssb_prctl_get();
585 default:
586 return -ENODEV;
587 }
588}
589
527void x86_spec_ctrl_setup_ap(void) 590void x86_spec_ctrl_setup_ap(void)
528{ 591{
529 if (boot_cpu_has(X86_FEATURE_IBRS)) 592 if (boot_cpu_has(X86_FEATURE_IBRS))