a0f7ab8a6a
cherry-pick from upstream 4.14
166 lines
5.5 KiB
Diff
166 lines
5.5 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Tim Chen <tim.c.chen@linux.intel.com>
|
|
Date: Mon, 20 Nov 2017 13:47:54 -0800
|
|
Subject: [PATCH] x86/spec_ctrl: Add lock to serialize changes to ibrs and ibpb
|
|
control
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
CVE-2017-5753
|
|
CVE-2017-5715
|
|
|
|
Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
|
|
Signed-off-by: Andy Whitcroft <apw@canonical.com>
|
|
Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
|
|
(cherry picked from commit 85789933bc45a3e763823675bd0d80e3e617f234)
|
|
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
|
|
---
|
|
arch/x86/kernel/cpu/intel.c | 22 ++++++++++++----------
|
|
arch/x86/kernel/cpu/microcode/core.c | 2 ++
|
|
kernel/smp.c | 4 ++++
|
|
kernel/sysctl.c | 14 +++++++++++++-
|
|
4 files changed, 31 insertions(+), 11 deletions(-)
|
|
|
|
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
|
|
index c69ea2efbed1..8d558e24783c 100644
|
|
--- a/arch/x86/kernel/cpu/intel.c
|
|
+++ b/arch/x86/kernel/cpu/intel.c
|
|
@@ -628,16 +628,18 @@ static void init_intel(struct cpuinfo_x86 *c)
|
|
|
|
init_intel_misc_features(c);
|
|
|
|
- if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
|
|
- printk_once(KERN_INFO "FEATURE SPEC_CTRL Present\n");
|
|
- set_ibrs_supported();
|
|
- set_ibpb_supported();
|
|
- if (ibrs_inuse)
|
|
- sysctl_ibrs_enabled = 1;
|
|
- if (ibpb_inuse)
|
|
- sysctl_ibpb_enabled = 1;
|
|
- } else {
|
|
- printk_once(KERN_INFO "FEATURE SPEC_CTRL Not Present\n");
|
|
+ if (!c->cpu_index) {
|
|
+ if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
|
|
+ printk(KERN_INFO "FEATURE SPEC_CTRL Present\n");
|
|
+ set_ibrs_supported();
|
|
+ set_ibpb_supported();
|
|
+ if (ibrs_inuse)
|
|
+ sysctl_ibrs_enabled = 1;
|
|
+ if (ibpb_inuse)
|
|
+ sysctl_ibpb_enabled = 1;
|
|
+ } else {
|
|
+ printk(KERN_INFO "FEATURE SPEC_CTRL Not Present\n");
|
|
+ }
|
|
}
|
|
}
|
|
|
|
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
|
|
index 6450aeda72fc..55086921d29e 100644
|
|
--- a/arch/x86/kernel/cpu/microcode/core.c
|
|
+++ b/arch/x86/kernel/cpu/microcode/core.c
|
|
@@ -538,12 +538,14 @@ static ssize_t reload_store(struct device *dev,
|
|
|
|
if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
|
|
printk_once(KERN_INFO "FEATURE SPEC_CTRL Present\n");
|
|
+ mutex_lock(&spec_ctrl_mutex);
|
|
set_ibrs_supported();
|
|
set_ibpb_supported();
|
|
if (ibrs_inuse)
|
|
sysctl_ibrs_enabled = 1;
|
|
if (ibpb_inuse)
|
|
sysctl_ibpb_enabled = 1;
|
|
+ mutex_unlock(&spec_ctrl_mutex);
|
|
}
|
|
|
|
mutex_unlock(µcode_mutex);
|
|
diff --git a/kernel/smp.c b/kernel/smp.c
|
|
index 3bece045f4a4..a224ec0c540c 100644
|
|
--- a/kernel/smp.c
|
|
+++ b/kernel/smp.c
|
|
@@ -519,6 +519,10 @@ int use_ibpb;
|
|
EXPORT_SYMBOL(use_ibpb);
|
|
#endif
|
|
|
|
+/* mutex to serialize IBRS & IBPB control changes */
|
|
+DEFINE_MUTEX(spec_ctrl_mutex);
|
|
+EXPORT_SYMBOL(spec_ctrl_mutex);
|
|
+
|
|
/*
|
|
* Setup routine for controlling SMP activation
|
|
*
|
|
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
|
|
index 69c37bd6251a..47a37792109d 100644
|
|
--- a/kernel/sysctl.c
|
|
+++ b/kernel/sysctl.c
|
|
@@ -69,6 +69,7 @@
|
|
#include <linux/mount.h>
|
|
|
|
#include <linux/uaccess.h>
|
|
+#include <linux/mutex.h>
|
|
#include <asm/processor.h>
|
|
|
|
#ifdef CONFIG_X86
|
|
@@ -2634,12 +2635,17 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
|
|
int proc_dointvec_ibrs_dump(struct ctl_table *table, int write,
|
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
|
{
|
|
- int ret;
|
|
+ int ret, orig_inuse;
|
|
unsigned int cpu;
|
|
|
|
+
|
|
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
printk("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
|
|
printk("use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
|
|
+ mutex_lock(&spec_ctrl_mutex);
|
|
+ orig_inuse = use_ibrs;
|
|
+ /* temporary halt to ibrs usage to dump ibrs values */
|
|
+ clear_ibrs_inuse();
|
|
for_each_online_cpu(cpu) {
|
|
u64 val;
|
|
|
|
@@ -2649,6 +2655,8 @@ int proc_dointvec_ibrs_dump(struct ctl_table *table, int write,
|
|
val = 0;
|
|
printk("read cpu %d ibrs val %lu\n", cpu, (unsigned long) val);
|
|
}
|
|
+ use_ibrs = orig_inuse;
|
|
+ mutex_unlock(&spec_ctrl_mutex);
|
|
return ret;
|
|
}
|
|
|
|
@@ -2661,6 +2669,7 @@ int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
|
|
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
pr_debug("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
|
|
pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
|
|
+ mutex_lock(&spec_ctrl_mutex);
|
|
if (sysctl_ibrs_enabled == 0) {
|
|
/* always set IBRS off */
|
|
set_ibrs_disabled();
|
|
@@ -2684,6 +2693,7 @@ int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
|
|
/* platform don't support ibrs */
|
|
sysctl_ibrs_enabled = 0;
|
|
}
|
|
+ mutex_unlock(&spec_ctrl_mutex);
|
|
pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
|
|
return ret;
|
|
}
|
|
@@ -2696,6 +2706,7 @@ int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
|
|
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
|
|
pr_debug("sysctl_ibrs_enabled = %u, sysctl_ibpb_enabled = %u\n", sysctl_ibrs_enabled, sysctl_ibpb_enabled);
|
|
pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
|
|
+ mutex_lock(&spec_ctrl_mutex);
|
|
if (sysctl_ibpb_enabled == 0)
|
|
set_ibpb_disabled();
|
|
else if (sysctl_ibpb_enabled == 1) {
|
|
@@ -2704,6 +2715,7 @@ int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
|
|
/* platform don't support ibpb */
|
|
sysctl_ibpb_enabled = 0;
|
|
}
|
|
+ mutex_unlock(&spec_ctrl_mutex);
|
|
pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
|
|
return ret;
|
|
}
|
|
--
|
|
2.14.2
|
|
|