pve-kernel-qoup/patches/kernel/0288-x86-spec_ctrl-Add-lock-to-serialize-changes-to-ibrs-.patch
Fabian Grünbichler a0f7ab8a6a fix #1622: i40e memory leak
cherry-pick from upstream 4.14
2018-01-19 12:43:16 +01:00

167 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(&microcode_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