]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
x86/spec_ctrl: Add lock to serialize changes to ibrs and ibpb control
authorTim Chen <tim.c.chen@linux.intel.com>
Mon, 20 Nov 2017 21:47:54 +0000 (13:47 -0800)
committerKirtikar Kashyap <kirtikar.kashyap@oracle.com>
Fri, 12 Jan 2018 18:19:57 +0000 (10:19 -0800)
Orabug: 27344012
CVE: CVE-2017-5715

Signed-off-by: Tim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: John Haxby <john.haxby@oracle.com>
Signed-off-by: Kirtikar Kashyap <kirtikar.kashyap@oracle.com>
arch/x86/kernel/cpu/intel.c
include/linux/smp.h
kernel/smp.c
kernel/sysctl.c

index 3d8b1170b3ab0ed7542234594d97a61da312a32f..f7c0167db1f714a184ce5343bf5549079ad174f0 100644 (file)
@@ -494,17 +494,18 @@ static void init_intel(struct cpuinfo_x86 *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");
+               }
        }
 }
 
index c340e38a6656283cbf3f44ac4a81fdfad6fcfc0f..3689de249d0ce0202dc245175e0303fa0bba9a72 100644 (file)
@@ -54,6 +54,7 @@ int smp_call_function_single_async(int cpu, struct call_single_data *csd);
 /* indicate usage of IBRS to control execution speculation */
 extern int use_ibrs;
 extern u32 sysctl_ibrs_enabled;
+extern struct mutex spec_ctrl_mutex;
 #define ibrs_supported         (use_ibrs & 0x2)
 #define ibrs_disabled          (use_ibrs & 0x4)
 static inline void set_ibrs_inuse(void)
index 8db57e98cd2d0817ce112be82705ba45516dcf41..d71ad2deb8057c4d9e63357f53406cd0c3f6ced9 100644 (file)
@@ -518,6 +518,10 @@ EXPORT_SYMBOL(use_ibrs);
 int use_ibpb;
 EXPORT_SYMBOL(use_ibpb);
 
+/* mutex to serialize IBRS & IBPB control changes */
+DEFINE_MUTEX(spec_ctrl_mutex);
+EXPORT_SYMBOL(spec_ctrl_mutex);
+
 /*
  * Setup routine for controlling SMP activation
  *
index 60726ece3bf2da223cbf6a520e38949098b8d9ee..857f1fd3c16aeecc53ef797d47231f65483aa723 100644 (file)
@@ -66,6 +66,7 @@
 #include <linux/kexec.h>
 #include <linux/ksplice.h>
 #include <linux/mount.h>
+#include <linux/mutex.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>
@@ -2844,12 +2845,17 @@ int proc_do_large_bitmap(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;
 
@@ -2859,6 +2865,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;
 }
 
@@ -2871,6 +2879,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();
@@ -2894,6 +2903,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;
 }
@@ -2906,6 +2916,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) {
@@ -2914,6 +2925,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;
 }