Commit bd597f2f authored by Tim Chen's avatar Tim Chen Committed by Khalid Elmously

x86/spec_ctrl: Add lock to serialize changes to ibrs and ibpb control

CVE-2017-5715 (Spectre v2 Intel)
Signed-off-by: default avatarTim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: default avatarAndy Whitcroft <apw@canonical.com>
(backported from commit 33e16ee8bd43aa4f065e17abbe9ed66457327b84)
Signed-off-by: default avatarAndy Whitcroft <apw@canonical.com>
Acked-by: default avatarColin Ian King <colin.king@canonical.com>
Acked-by: default avatarKamal Mostafa <kamal@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent df043b74
...@@ -529,16 +529,18 @@ static void init_intel(struct cpuinfo_x86 *c) ...@@ -529,16 +529,18 @@ static void init_intel(struct cpuinfo_x86 *c)
init_intel_energy_perf(c); init_intel_energy_perf(c);
if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) { if (!c->cpu_index) {
printk_once(KERN_INFO "FEATURE SPEC_CTRL Present\n"); if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
set_ibrs_supported(); printk(KERN_INFO "FEATURE SPEC_CTRL Present\n");
set_ibpb_supported(); set_ibrs_supported();
if (ibrs_inuse) set_ibpb_supported();
sysctl_ibrs_enabled = 1; if (ibrs_inuse)
if (ibpb_inuse) sysctl_ibrs_enabled = 1;
sysctl_ibpb_enabled = 1; if (ibpb_inuse)
} else { sysctl_ibpb_enabled = 1;
printk_once(KERN_INFO "FEATURE SPEC_CTRL Not Present\n"); } else {
printk(KERN_INFO "FEATURE SPEC_CTRL Not Present\n");
}
} }
} }
......
...@@ -422,12 +422,14 @@ static ssize_t reload_store(struct device *dev, ...@@ -422,12 +422,14 @@ static ssize_t reload_store(struct device *dev,
if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) { if (boot_cpu_has(X86_FEATURE_SPEC_CTRL)) {
printk_once(KERN_INFO "FEATURE SPEC_CTRL Present\n"); printk_once(KERN_INFO "FEATURE SPEC_CTRL Present\n");
mutex_lock(&spec_ctrl_mutex);
set_ibrs_supported(); set_ibrs_supported();
set_ibpb_supported(); set_ibpb_supported();
if (ibrs_inuse) if (ibrs_inuse)
sysctl_ibrs_enabled = 1; sysctl_ibrs_enabled = 1;
if (ibpb_inuse) if (ibpb_inuse)
sysctl_ibpb_enabled = 1; sysctl_ibpb_enabled = 1;
mutex_unlock(&spec_ctrl_mutex);
} }
mutex_unlock(&microcode_mutex); mutex_unlock(&microcode_mutex);
......
...@@ -520,6 +520,10 @@ int use_ibpb; ...@@ -520,6 +520,10 @@ int use_ibpb;
EXPORT_SYMBOL(use_ibpb); EXPORT_SYMBOL(use_ibpb);
#endif #endif
/* mutex to serialize IBRS & IBPB control changes */
DEFINE_MUTEX(spec_ctrl_mutex);
EXPORT_SYMBOL(spec_ctrl_mutex);
/* /*
* Setup routine for controlling SMP activation * Setup routine for controlling SMP activation
* *
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
#include <linux/mount.h> #include <linux/mount.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/mutex.h>
#include <asm/processor.h> #include <asm/processor.h>
#ifdef CONFIG_X86 #ifdef CONFIG_X86
...@@ -2424,12 +2425,17 @@ int proc_dointvec_minmax(struct ctl_table *table, int write, ...@@ -2424,12 +2425,17 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
int proc_dointvec_ibrs_dump(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) void __user *buffer, size_t *lenp, loff_t *ppos)
{ {
int ret; int ret, orig_inuse;
unsigned int cpu; unsigned int cpu;
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 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("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); 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) { for_each_online_cpu(cpu) {
u64 val; u64 val;
...@@ -2439,6 +2445,8 @@ int proc_dointvec_ibrs_dump(struct ctl_table *table, int write, ...@@ -2439,6 +2445,8 @@ int proc_dointvec_ibrs_dump(struct ctl_table *table, int write,
val = 0; val = 0;
printk("read cpu %d ibrs val %lu\n", cpu, (unsigned long) val); printk("read cpu %d ibrs val %lu\n", cpu, (unsigned long) val);
} }
use_ibrs = orig_inuse;
mutex_unlock(&spec_ctrl_mutex);
return ret; return ret;
} }
...@@ -2451,6 +2459,7 @@ int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write, ...@@ -2451,6 +2459,7 @@ int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 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("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); pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
mutex_lock(&spec_ctrl_mutex);
if (sysctl_ibrs_enabled == 0) { if (sysctl_ibrs_enabled == 0) {
/* always set IBRS off */ /* always set IBRS off */
set_ibrs_disabled(); set_ibrs_disabled();
...@@ -2474,6 +2483,7 @@ int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write, ...@@ -2474,6 +2483,7 @@ int proc_dointvec_ibrs_ctrl(struct ctl_table *table, int write,
/* platform don't support ibrs */ /* platform don't support ibrs */
sysctl_ibrs_enabled = 0; sysctl_ibrs_enabled = 0;
} }
mutex_unlock(&spec_ctrl_mutex);
pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb); pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
return ret; return ret;
} }
...@@ -2486,6 +2496,7 @@ int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write, ...@@ -2486,6 +2496,7 @@ int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); 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("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); pr_debug("before:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
mutex_lock(&spec_ctrl_mutex);
if (sysctl_ibpb_enabled == 0) if (sysctl_ibpb_enabled == 0)
set_ibpb_disabled(); set_ibpb_disabled();
else if (sysctl_ibpb_enabled == 1) { else if (sysctl_ibpb_enabled == 1) {
...@@ -2494,6 +2505,7 @@ int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write, ...@@ -2494,6 +2505,7 @@ int proc_dointvec_ibpb_ctrl(struct ctl_table *table, int write,
/* platform don't support ibpb */ /* platform don't support ibpb */
sysctl_ibpb_enabled = 0; sysctl_ibpb_enabled = 0;
} }
mutex_unlock(&spec_ctrl_mutex);
pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb); pr_debug("after:use_ibrs = %d, use_ibpb = %d\n", use_ibrs, use_ibpb);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment