All of lore.kernel.org
 help / color / mirror / Atom feed
* [MODERATED] [PATCH v2] Linux Patch 1/1
@ 2018-04-26  0:11 Tim Chen
  2018-04-26  3:15 ` [MODERATED] " Jon Masters
                   ` (3 more replies)
  0 siblings, 4 replies; 46+ messages in thread
From: Tim Chen @ 2018-04-26  0:11 UTC (permalink / raw)
  To: speck


[-- Attachment #1.1: Type: text/plain, Size: 14210 bytes --]


From bf437945b231c9daaa3b927f50e57a868b7757d9 Mon Sep 17 00:00:00 2001
From: Tim Chen <tim.c.chen@linux.intel.com>
Date: Mon, 23 Apr 2018 05:57:53 -0700
Subject: [PATCH v2] Linux Patch 1/1 

x86/ssb: Enable option to mitigate SSB by explicit prctl

Processes that are unable to use other software mitigations and execute
untrusted code may want to disable speculative store bypass. This patch
adds a new prctl : PR_SET_RDS_MODE.
The prctl allows the enable/disable of reduced data speculation mode
to mitigate speculative store bypass vulnerability of the
current process.

The prctl mode is inherited to children to handle threads and allow wrappers,
but it is not broadcast to all threads in the same process. It is generally
safe to inherit because it doesn't allow any new attacks, but just prevents
them.

It also adds a matching prctl PR_GET_RDS_MODE to retrieve that state.

This patch is applied on top of v4 of Konrad's SSB patchset.

v2:
Switch from using RDS on seccomp processes to using an explicit
prctl to enable RDS.

Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
---
 Documentation/admin-guide/kernel-parameters.txt |  4 ++
 arch/x86/include/asm/nospec-branch.h            | 17 +++++
 arch/x86/include/asm/thread_info.h              |  2 +
 arch/x86/kernel/cpu/bugs.c                      | 86 +++++++++++++++++++++++--
 arch/x86/kernel/cpu/intel.c                     |  4 +-
 arch/x86/kernel/process_64.c                    | 12 ++++
 include/uapi/linux/prctl.h                      | 12 ++++
 kernel/fork.c                                   |  8 +++
 kernel/sys.c                                    | 16 +++++
 9 files changed, 155 insertions(+), 6 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index a2d337b..1f95161 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4053,6 +4053,10 @@
 			auto - kernel detects whether your CPU model contains a
 			       vulnerable implementation of Speculative Store
 			       Bypass and picks the most appropriate mitigation
+			prctl - disable Speculative Store Bypass for processes
+				via prctl. Processes run normally with
+				Speculative Store bypass by default unless
+				told otherwise by prctl.
 
 			Not specifying this option is equivalent to
 			spec_store_bypass_disable=auto.
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index 6f3d224..a6bb9da 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -3,10 +3,12 @@
 #ifndef _ASM_X86_NOSPEC_BRANCH_H_
 #define _ASM_X86_NOSPEC_BRANCH_H_
 
+#include <linux/jump_label.h>
 #include <asm/alternative.h>
 #include <asm/alternative-asm.h>
 #include <asm/cpufeatures.h>
 #include <asm/msr-index.h>
+#include <asm/percpu.h>
 
 /*
  * Fill the CPU return stack buffer.
@@ -242,11 +244,15 @@ extern void x86_restore_host_spec_ctrl(u64);
 enum ssb_mitigation {
 	SPEC_STORE_BYPASS_NONE,
 	SPEC_STORE_BYPASS_DISABLE,
+	SPEC_STORE_BYPASS_PRCTL,
 };
 
 extern char __indirect_thunk_start[];
 extern char __indirect_thunk_end[];
 
+/* cpu's MSR_IA32_SPEC_CTRL state for speculation store bypass mitigation */
+DECLARE_PER_CPU(int, rds_msr_val);
+
 /*
  * On VMEXIT we must ensure that no RSB predictions learned in the guest
  * can be followed in the host, by overwriting the RSB completely. Both
@@ -310,6 +316,17 @@ do {									\
 	preempt_enable();						\
 } while (0)
 
+/*
+ * speculation store bypass vulnerabilities mitigation functions.
+ *
+ * Should be called only from pre-emption off paths.
+ *
+ */
+
+void enable_speculative_store_bypass_mitigation(void);
+void disable_speculative_store_bypass_mitigation(void);
+
+DECLARE_STATIC_KEY_FALSE(specctrl_rds);
 #endif /* __ASSEMBLY__ */
 
 /*
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index a5d9521..f401321 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -79,6 +79,7 @@ struct thread_info {
 #define TIF_SIGPENDING		2	/* signal pending */
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_SINGLESTEP		4	/* reenable singlestep on user return*/
+#define TIF_RDS			5	/* Reduced data speculation */
 #define TIF_SYSCALL_EMU		6	/* syscall emulation active */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
 #define TIF_SECCOMP		8	/* secure computing */
@@ -105,6 +106,7 @@ struct thread_info {
 #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1 << TIF_SINGLESTEP)
+#define _TIF_RDS		(1 << TIF_RDS)
 #define _TIF_SYSCALL_EMU	(1 << TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index f519214..10819f7 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -12,6 +12,7 @@
 #include <linux/utsname.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
+#include <linux/prctl.h>
 
 #include <asm/nospec-branch.h>
 #include <asm/cmdline.h>
@@ -133,7 +134,7 @@ EXPORT_SYMBOL_GPL(x86_set_spec_ctrl);
 
 u64 x86_get_spec_ctrl(void)
 {
-	return x86_spec_ctrl_base;
+	return x86_spec_ctrl_base | __this_cpu_read(rds_msr_val);
 }
 EXPORT_SYMBOL_GPL(x86_get_spec_ctrl);
 
@@ -148,10 +149,12 @@ EXPORT_SYMBOL_GPL(x86_set_guest_spec_ctrl);
 
 void x86_restore_host_spec_ctrl(u64 guest_spec_ctrl)
 {
-	if (x86_get_spec_ctrl() == guest_spec_ctrl)
+	u64 host_val = x86_get_spec_ctrl();
+
+	if (host_val == guest_spec_ctrl)
 		return;
 	else
-		wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+		wrmsrl(MSR_IA32_SPEC_CTRL, host_val);
 }
 EXPORT_SYMBOL_GPL(x86_restore_host_spec_ctrl);
 
@@ -376,16 +379,26 @@ static void __init spectre_v2_select_mitigation(void)
 
 static enum ssb_mitigation ssb_mode = SPEC_STORE_BYPASS_NONE;
 
+/* dynamic reduced data speculation in use */
+DEFINE_STATIC_KEY_FALSE(specctrl_rds);
+EXPORT_SYMBOL(specctrl_rds);
+
+/* current MSR_IA32_SPEC_CTRL state for ssb mitigation */
+DEFINE_PER_CPU(int, rds_msr_val);
+EXPORT_SYMBOL(rds_msr_val);
+
 /* The kernel command line selection */
 enum ssb_mitigation_cmd {
 	SPEC_STORE_BYPASS_CMD_NONE,
 	SPEC_STORE_BYPASS_CMD_AUTO,
 	SPEC_STORE_BYPASS_CMD_ON,
+	SPEC_STORE_BYPASS_CMD_PRCTL,
 };
 
 static const char *ssb_strings[] = {
 	[SPEC_STORE_BYPASS_NONE]	= "Vulnerable",
-	[SPEC_STORE_BYPASS_DISABLE]	= "Mitigation: Speculative Store Bypass disabled"
+	[SPEC_STORE_BYPASS_DISABLE]	= "Mitigation: Speculative Store Bypass disabled",
+	[SPEC_STORE_BYPASS_PRCTL]	= "Mitigation: Speculative Store Bypass disabled via prctl"
 };
 
 static const struct {
@@ -395,8 +408,61 @@ static const struct {
 	{ "auto",	SPEC_STORE_BYPASS_CMD_AUTO }, /* Platform decides */
 	{ "on",		SPEC_STORE_BYPASS_CMD_ON },   /* Disable Speculative Store Bypass */
 	{ "off",	SPEC_STORE_BYPASS_CMD_NONE }, /* Don't touch Speculative Store Bypass */
+	{ "prctl",	SPEC_STORE_BYPASS_CMD_PRCTL }, /* disable Speculative Store Bypass via prctl */
 };
 
+void enable_speculative_store_bypass_mitigation(void)
+{
+       if (static_branch_unlikely(&specctrl_rds) &&
+           /* need to toggle msr? */
+           __this_cpu_read(rds_msr_val) != SPEC_CTRL_RDS) {
+               wrmsrl(MSR_IA32_SPEC_CTRL, SPEC_CTRL_RDS | x86_spec_ctrl_base);
+               __this_cpu_write(rds_msr_val, SPEC_CTRL_RDS);
+       }
+}
+
+void disable_speculative_store_bypass_mitigation(void)
+{
+       if (static_branch_unlikely(&specctrl_rds) &&
+           /* need to toggle msr? */
+           __this_cpu_read(rds_msr_val) != 0) {
+               wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+               __this_cpu_write(rds_msr_val, 0);
+       }
+}
+
+int arch_prctl_set_rds(struct task_struct *p, unsigned long val)
+{
+	if (val == PR_RDS_MODE_ENABLE) {
+		set_tsk_thread_flag(p, TIF_RDS);
+		if (p == current)
+			enable_speculative_store_bypass_mitigation();
+	} else if (val == PR_RDS_MODE_DISABLE) {
+		clear_tsk_thread_flag(p, TIF_RDS);
+		if (p == current)
+			disable_speculative_store_bypass_mitigation();
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+int arch_prctl_get_rds(struct task_struct *p)
+{
+	if (test_tsk_thread_flag(p, TIF_RDS))
+		return PR_RDS_MODE_ENABLE;
+
+	return PR_RDS_MODE_DISABLE;
+}
+
+void arch_prctl_copy_rds_mode(struct task_struct *parent, struct task_struct *child)
+{
+	if (test_tsk_thread_flag(parent, TIF_RDS))
+		set_tsk_thread_flag(child, TIF_RDS);
+	else
+		clear_tsk_thread_flag(child, TIF_RDS);
+}
+
 static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
 {
 	char arg[20];
@@ -445,6 +511,7 @@ static void __init ssb_select_mitigation(void)
 	     cmd == SPEC_STORE_BYPASS_CMD_AUTO))
 		return;
 
+again:
 	switch (cmd) {
 	case SPEC_STORE_BYPASS_CMD_AUTO:
 		/*
@@ -452,9 +519,17 @@ static void __init ssb_select_mitigation(void)
 		 */
 		if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
 			break;
+		/* Choose prctl as the default mode */
+		cmd = SPEC_STORE_BYPASS_CMD_PRCTL;
+		goto again;
+		break;
 	case SPEC_STORE_BYPASS_CMD_ON:
 		mode = SPEC_STORE_BYPASS_DISABLE;
 		break;
+	case SPEC_STORE_BYPASS_CMD_PRCTL:
+		mode = SPEC_STORE_BYPASS_PRCTL;
+		static_branch_enable(&specctrl_rds);
+		break;
 	case SPEC_STORE_BYPASS_CMD_NONE:
 		break;
 	}
@@ -463,7 +538,8 @@ static void __init ssb_select_mitigation(void)
 	pr_info("%s\n", ssb_strings[mode]);
 
 	if (mode != SPEC_STORE_BYPASS_NONE) {
-		if (boot_cpu_has(X86_FEATURE_RDS))
+		if (boot_cpu_has(X86_FEATURE_RDS) &&
+		    !static_branch_unlikely(&specctrl_rds))
 			x86_spec_ctrl_base |= SPEC_CTRL_RDS;
 
 		setup_force_cpu_cap(X86_FEATURE_DISABLE_SSB);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index e0f0596..98ca193 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -772,7 +772,9 @@ static void init_intel(struct cpuinfo_x86 *c)
 
 	init_intel_misc_features(c);
 
-	if (cpu_has(c, X86_FEATURE_DISABLE_SSB) && cpu_has(c, X86_FEATURE_RDS)) {
+	if (cpu_has(c, X86_FEATURE_DISABLE_SSB) &&
+	    cpu_has(c, X86_FEATURE_RDS) &&
+	    !static_branch_unlikely(&specctrl_rds)) {
 		x86_set_spec_ctrl(SPEC_CTRL_RDS);
 	}
 }
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 4b100fe..c8c5cc4 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -54,6 +54,7 @@
 #include <asm/vdso.h>
 #include <asm/intel_rdt_sched.h>
 #include <asm/unistd.h>
+#include <asm/nospec-branch.h>
 #ifdef CONFIG_IA32_EMULATION
 /* Not included via unistd.h */
 #include <asm/unistd_32_ia32.h>
@@ -529,6 +530,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
 	/* Load the Intel cache allocation PQR MSR. */
 	intel_rdt_sched_in();
 
+	if (test_tsk_thread_flag(next_p, TIF_RDS))
+		/*
+		 * Reduce data speculation for processes that
+		 * have reduced data speculation option turned
+		 * on via prctl.  This provides protection against speculation
+		 * store bypass attack for untrusted code within the process.
+		 */
+		enable_speculative_store_bypass_mitigation();
+	else
+		disable_speculative_store_bypass_mitigation();
+
 	return prev_p;
 }
 
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index af5f8c2..7635b9a 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -207,4 +207,16 @@ struct prctl_mm_map {
 # define PR_SVE_VL_LEN_MASK		0xffff
 # define PR_SVE_VL_INHERIT		(1 << 17) /* inherit across exec */
 
+/*
+ * Reduced Data Speculation controls
+ *
+ * Set this on a task so it will run with reduced level of data speculation
+ * to mitigate against speculative store bypass attack.
+ */
+#define PR_SET_RDS_MODE		53	/* set reduced data speculation mode of process */
+#define PR_RDS_MODE_DISABLE	0       /* Disable reduced data speculation mode */
+#define PR_RDS_MODE_ENABLE	1       /* Enable reduced data speculation mode */
+
+#define PR_GET_RDS_MODE		54	/* get reduced data speculation mode of process */
+
 #endif /* _LINUX_PRCTL_H */
diff --git a/kernel/fork.c b/kernel/fork.c
index a5d21c4..8fe9c80 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1561,6 +1561,11 @@ static inline void rcu_copy_process(struct task_struct *p)
 #endif /* #ifdef CONFIG_TASKS_RCU */
 }
 
+void __weak arch_prctl_copy_rds_mode(struct task_struct *parent, struct task_struct *child)
+{
+	return;
+}
+
 /*
  * This creates a new process as a copy of the old one,
  * but does not actually start it yet.
@@ -1633,6 +1638,9 @@ static __latent_entropy struct task_struct *copy_process(
 	if (!p)
 		goto fork_out;
 
+	/* Copy the reduced data speculation mode from parent to child */
+	arch_prctl_copy_rds_mode(current, p);
+
 	/*
 	 * This _must_ happen before we call free_task(), i.e. before we jump
 	 * to any of the bad_fork_* labels. This is to avoid freeing
diff --git a/kernel/sys.c b/kernel/sys.c
index ad69218..8fbb698 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -2242,6 +2242,16 @@ static int propagate_has_child_subreaper(struct task_struct *p, void *data)
 	return 1;
 }
 
+int __weak arch_prctl_set_rds(struct task_struct *p, unsigned long arg)
+{
+	return 0;
+}
+
+int __weak arch_prctl_get_rds(struct task_struct *p)
+{
+	return 0;
+}
+
 SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 		unsigned long, arg4, unsigned long, arg5)
 {
@@ -2450,6 +2460,12 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
 	case PR_SVE_GET_VL:
 		error = SVE_GET_VL();
 		break;
+	case PR_SET_RDS_MODE:
+		error = arch_prctl_set_rds(me, arg2);
+		break;
+	case PR_GET_RDS_MODE:
+		error = arch_prctl_get_rds(me);
+		break;
 	default:
 		error = -EINVAL;
 		break;
-- 
2.9.4


^ permalink raw reply related	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2018-05-07 16:40 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-26  0:11 [MODERATED] [PATCH v2] Linux Patch 1/1 Tim Chen
2018-04-26  3:15 ` [MODERATED] " Jon Masters
2018-04-26 17:03   ` Tim Chen
2018-04-26  3:29 ` Jon Masters
2018-04-26 12:03   ` Thomas Gleixner
2018-04-26 16:48     ` [MODERATED] " Tim Chen
2018-04-26 16:18 ` Jon Masters
2018-04-27 16:08 ` Thomas Gleixner
2018-04-27 16:47   ` [MODERATED] " Borislav Petkov
2018-04-27 17:13     ` Jon Masters
2018-04-27 17:32       ` Borislav Petkov
2018-04-27 17:48         ` Thomas Gleixner
2018-04-27 18:09           ` [MODERATED] " Andi Kleen
2018-04-27 18:17             ` Thomas Gleixner
2018-04-27 18:20               ` Thomas Gleixner
2018-04-27 18:30                 ` [MODERATED] " Linus Torvalds
2018-04-27 18:36                   ` Thomas Gleixner
2018-04-27 18:53                     ` [MODERATED] " Linus Torvalds
2018-04-27 19:14                       ` Andi Kleen
2018-04-27 19:37                       ` Jon Masters
2018-04-27 19:52                         ` Linus Torvalds
2018-04-27 20:01                           ` Jon Masters
2018-05-03 12:55                           ` Jiri Kosina
2018-05-03 16:24                             ` Linus Torvalds
2018-05-03 19:40                               ` Jiri Kosina
2018-05-04  3:51                                 ` Linus Torvalds
2018-05-04  6:00                                   ` Jiri Kosina
2018-05-04  6:03                                     ` Jiri Kosina
2018-05-07 16:40                                   ` [MODERATED] " Dave Hansen
2018-04-27 19:26                   ` [MODERATED] " Tim Chen
2018-04-27 19:57                     ` Jon Masters
2018-04-27 20:07                       ` Tim Chen
2018-04-27 20:20                         ` Thomas Gleixner
2018-04-27 20:37                       ` Thomas Gleixner
2018-04-28  3:57                         ` [MODERATED] " Tim Chen
2018-04-28 12:26                           ` Thomas Gleixner
2018-04-28 17:14                             ` [MODERATED] " Tim Chen
2018-04-27 22:52                     ` Thomas Gleixner
2018-04-27 18:45               ` [MODERATED] " Andi Kleen
2018-04-27 19:08                 ` Thomas Gleixner
2018-04-27 19:25                   ` [MODERATED] " Andi Kleen
2018-04-27 19:52                     ` Thomas Gleixner
2018-04-27 17:50         ` [MODERATED] " Andi Kleen
2018-04-27 17:58   ` Thomas Gleixner
2018-04-27 19:01   ` [MODERATED] " Tim Chen
2018-04-27 19:19     ` Thomas Gleixner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.