Skip to content

Commit 10383e7

Browse files
KAGA-KOKOkonradwilk
authored andcommitted
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 <[email protected]> Reviewed-by: Konrad Rzeszutek Wilk <[email protected]> (cherry picked from commit a73ec77) Orabug: 28034177 CVE: CVE-2018-3639 Signed-off-by: Konrad Rzeszutek Wilk <[email protected]> Tested-by: Mihai Carabas <[email protected]> Reviewed-by: Mihai Carabas <[email protected]> Reviewed-by: John Haxby <[email protected]>
1 parent a7514ec commit 10383e7

File tree

3 files changed

+79
-11
lines changed

3 files changed

+79
-11
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3974,7 +3974,11 @@
39743974
off - Unconditionally enable Speculative Store Bypass
39753975
auto - Kernel detects whether the CPU model contains an
39763976
implementation of Speculative Store Bypass and
3977-
picks the most appropriate mitigation
3977+
picks the most appropriate mitigation.
3978+
prctl - Control Speculative Store Bypass per thread
3979+
via prctl. Speculative Store Bypass is enabled
3980+
for a process by default. The state of the control
3981+
is inherited on fork.
39783982

39793983
Not specifying this option is equivalent to
39803984
spec_store_bypass_disable=auto.

arch/x86/include/asm/nospec-branch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ extern u64 x86_spec_ctrl_get_default(void);
232232
enum ssb_mitigation {
233233
SPEC_STORE_BYPASS_NONE,
234234
SPEC_STORE_BYPASS_DISABLE,
235+
SPEC_STORE_BYPASS_PRCTL,
235236
};
236237

237238
extern char __indirect_thunk_start[];

arch/x86/kernel/cpu/bugs.c

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
#include <linux/utsname.h>
1313
#include <linux/cpu.h>
1414
#include <linux/module.h>
15+
#include <linux/nospec.h>
16+
#include <linux/prctl.h>
1517

1618
#include <asm/spec-ctrl.h>
1719
#include <asm/cmdline.h>
@@ -653,20 +655,23 @@ enum ssb_mitigation_cmd {
653655
SPEC_STORE_BYPASS_CMD_NONE,
654656
SPEC_STORE_BYPASS_CMD_AUTO,
655657
SPEC_STORE_BYPASS_CMD_ON,
658+
SPEC_STORE_BYPASS_CMD_PRCTL,
656659
};
657660

658661
static const char *ssb_strings[] = {
659662
[SPEC_STORE_BYPASS_NONE] = "Vulnerable",
660-
[SPEC_STORE_BYPASS_DISABLE] = "Mitigation: Speculative Store Bypass disabled"
663+
[SPEC_STORE_BYPASS_DISABLE] = "Mitigation: Speculative Store Bypass disabled",
664+
[SPEC_STORE_BYPASS_PRCTL] = "Mitigation: Speculative Store Bypass disabled via prctl"
661665
};
662666

663667
static const struct {
664668
const char *option;
665669
enum ssb_mitigation_cmd cmd;
666670
} ssb_mitigation_options[] = {
667-
{ "auto", SPEC_STORE_BYPASS_CMD_AUTO }, /* Platform decides */
668-
{ "on", SPEC_STORE_BYPASS_CMD_ON }, /* Disable Speculative Store Bypass */
669-
{ "off", SPEC_STORE_BYPASS_CMD_NONE }, /* Don't touch Speculative Store Bypass */
671+
{ "auto", SPEC_STORE_BYPASS_CMD_AUTO }, /* Platform decides */
672+
{ "on", SPEC_STORE_BYPASS_CMD_ON }, /* Disable Speculative Store Bypass */
673+
{ "off", SPEC_STORE_BYPASS_CMD_NONE }, /* Don't touch Speculative Store Bypass */
674+
{ "prctl", SPEC_STORE_BYPASS_CMD_PRCTL }, /* Disable Speculative Store Bypass via prctl */
670675
};
671676

672677
static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
@@ -716,14 +721,15 @@ static enum ssb_mitigation_cmd __init __ssb_select_mitigation(void)
716721

717722
switch (cmd) {
718723
case SPEC_STORE_BYPASS_CMD_AUTO:
719-
/*
720-
* AMD platforms by default don't need SSB mitigation.
721-
*/
722-
if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
723-
break;
724+
/* Choose prctl as the default mode */
725+
mode = SPEC_STORE_BYPASS_PRCTL;
726+
break;
724727
case SPEC_STORE_BYPASS_CMD_ON:
725728
mode = SPEC_STORE_BYPASS_DISABLE;
726729
break;
730+
case SPEC_STORE_BYPASS_CMD_PRCTL:
731+
mode = SPEC_STORE_BYPASS_PRCTL;
732+
break;
727733
case SPEC_STORE_BYPASS_CMD_NONE:
728734
break;
729735
}
@@ -734,7 +740,7 @@ static enum ssb_mitigation_cmd __init __ssb_select_mitigation(void)
734740
* - X86_FEATURE_RDS - CPU is able to turn off speculative store bypass
735741
* - X86_FEATURE_SPEC_STORE_BYPASS_DISABLE - engage the mitigation
736742
*/
737-
if (mode != SPEC_STORE_BYPASS_NONE) {
743+
if (mode == SPEC_STORE_BYPASS_DISABLE) {
738744
setup_force_cpu_cap(X86_FEATURE_SPEC_STORE_BYPASS_DISABLE);
739745
/*
740746
* Intel uses the SPEC CTRL MSR Bit(2) for this, while AMD uses
@@ -765,6 +771,63 @@ static void ssb_select_mitigation()
765771

766772
#undef pr_fmt
767773

774+
static int ssb_prctl_set(unsigned long ctrl)
775+
{
776+
bool rds = !!test_tsk_thread_flag(current, TIF_RDS);
777+
778+
if (ssb_mode != SPEC_STORE_BYPASS_PRCTL)
779+
return -ENXIO;
780+
781+
if (ctrl == PR_SPEC_ENABLE)
782+
clear_tsk_thread_flag(current, TIF_RDS);
783+
else
784+
set_tsk_thread_flag(current, TIF_RDS);
785+
786+
if (rds != !!test_tsk_thread_flag(current, TIF_RDS))
787+
speculative_store_bypass_update();
788+
789+
return 0;
790+
}
791+
792+
static int ssb_prctl_get(void)
793+
{
794+
switch (ssb_mode) {
795+
case SPEC_STORE_BYPASS_DISABLE:
796+
return PR_SPEC_DISABLE;
797+
case SPEC_STORE_BYPASS_PRCTL:
798+
if (test_tsk_thread_flag(current, TIF_RDS))
799+
return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
800+
return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
801+
default:
802+
if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
803+
return PR_SPEC_ENABLE;
804+
return PR_SPEC_NOT_AFFECTED;
805+
}
806+
}
807+
808+
int arch_prctl_spec_ctrl_set(unsigned long which, unsigned long ctrl)
809+
{
810+
if (ctrl != PR_SPEC_ENABLE && ctrl != PR_SPEC_DISABLE)
811+
return -ERANGE;
812+
813+
switch (which) {
814+
case PR_SPEC_STORE_BYPASS:
815+
return ssb_prctl_set(ctrl);
816+
default:
817+
return -ENODEV;
818+
}
819+
}
820+
821+
int arch_prctl_spec_ctrl_get(unsigned long which)
822+
{
823+
switch (which) {
824+
case PR_SPEC_STORE_BYPASS:
825+
return ssb_prctl_get();
826+
default:
827+
return -ENODEV;
828+
}
829+
}
830+
768831
void x86_spec_ctrl_setup_ap(void)
769832
{
770833
if (boot_cpu_has(X86_FEATURE_IBRS))

0 commit comments

Comments
 (0)