diff mbox series

[SRU,Trusty,1/3] UBUNTU: SAUCE: x86/speculation: Cleanup IBPB runtime control handling (v2)

Message ID 20181121173113.13474-2-juergh@canonical.com
State New
Headers show
Series Cleanups for CVE-2017-5715 (Spectre v2) | expand

Commit Message

Juerg Haefliger Nov. 21, 2018, 5:31 p.m. UTC
Cleanup the code to match Xenial. Functional changes introduced:
  - Return an error when someone tries to enable IBPB via procfs on HW that
    doesn't have IBPB support.
  - Write every IBPB state change to the kernel log.

CVE-2017-5715

Signed-off-by: Juerg Haefliger <juergh@canonical.com>
---
 arch/x86/include/asm/nospec-branch.h |  6 ++++--
 arch/x86/kernel/cpu/bugs.c           | 23 +++++++++++-----------
 kernel/sysctl.c                      | 29 ++++++++++++++++------------
 3 files changed, 32 insertions(+), 26 deletions(-)
diff mbox series

Patch

diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index dd8f0790fbd9..3cc7e65fbb3a 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -190,9 +190,11 @@ 
 # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
 #endif
 
-/* The IBPB and IBRS runtime control knobs */
+/* The IBPB runtime control knob */
 extern unsigned int ibpb_enabled;
-void ibpb_enable(void);
+int set_ibpb_enabled(unsigned int);
+
+/* The IBRS runtime control knob */
 extern unsigned int ibrs_enabled;
 void ibrs_enable(void);
 
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 5b1d8522764e..b4a0a26efc0d 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -428,19 +428,18 @@  retpoline_auto:
 	spectre_v2_enabled = mode;
 	pr_info("%s\n", spectre_v2_strings[mode]);
 
-	/* Initialize Indirect Branch Prediction Barrier if supported */
+	/*
+	 * Initialize Indirect Branch Prediction Barrier if supported and not
+	 * disabled on the commandline
+	 */
 	if (boot_cpu_has(X86_FEATURE_IBPB)) {
 		setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
-
-		/*
-		 * Enable IBPB support if it's not turned off on the
-		 * commandline.
-		 */
-		if (!noibpb)
-			ibpb_enable();
-
-		pr_info("%s Indirect Branch Prediction Barrier\n",
-			ibpb_enabled ? "Enabling" : "Disabling");
+		if (noibpb) {
+			/* IBPB disabled via commandline */
+			set_ibpb_enabled(0);
+		} else {
+			set_ibpb_enabled(1);
+		}
 	}
 
 	/*
@@ -876,7 +875,7 @@  static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
 
 	case X86_BUG_SPECTRE_V2:
 		return sprintf(buf, "%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
-			       ibpb_enabled && boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
+			       ibpb_enabled ? ", IBPB" : "",
 			       boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "");
 
 	case X86_BUG_SPEC_STORE_BYPASS:
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index e18e18bebd92..9d3084581410 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -203,31 +203,37 @@  static int proc_dostring_coredump(struct ctl_table *table, int write,
 DEFINE_MUTEX(spec_ctrl_mutex);
 
 unsigned int ibpb_enabled = 0;
-EXPORT_SYMBOL(ibpb_enabled);
+EXPORT_SYMBOL(ibpb_enabled);   /* Required in some modules */
 
 static unsigned int __ibpb_enabled = 0;   /* procfs shadow variable */
 
-static void set_ibpb_enabled(unsigned int val)
+int set_ibpb_enabled(unsigned int val)
 {
+	int error = 0;
+
 	mutex_lock(&spec_ctrl_mutex);
 
 	/* Only enable IBPB if the CPU supports it */
-	if (val && boot_cpu_has(X86_FEATURE_USE_IBPB))
-		ibpb_enabled = 1;
-	else
+	if (boot_cpu_has(X86_FEATURE_IBPB)) {
+		ibpb_enabled = val;
+		pr_info("Spectre V2 : Spectre v2 mitigation: %s Indirect "
+			"Branch Prediction Barrier\n",
+			ibpb_enabled ? "Enabling" : "Disabling");
+	} else {
 		ibpb_enabled = 0;
+		if (val) {
+			/* IBPB is not supported but we try to turn it on */
+			error = -EINVAL;
+		}
+	}
 
 	/* Update the shadow variable */
 	__ibpb_enabled = ibpb_enabled;
 
 	mutex_unlock(&spec_ctrl_mutex);
-}
 
-inline void ibpb_enable(void)
-{
-	set_ibpb_enabled(1);
+	return error;
 }
-EXPORT_SYMBOL(ibpb_enable);
 
 static int ibpb_enabled_handler(struct ctl_table *table, int write,
 				void __user *buffer, size_t *lenp,
@@ -239,8 +245,7 @@  static int ibpb_enabled_handler(struct ctl_table *table, int write,
 	if (error)
 		return error;
 
-	set_ibpb_enabled(__ibpb_enabled);
-	return 0;
+	return set_ibpb_enabled(__ibpb_enabled);
 }
 
 unsigned int ibrs_enabled = 0;