From: Kanth Ghatraju Date: Thu, 28 Mar 2019 17:57:23 +0000 (-0400) Subject: x86/speculation/mds: Add debugfs for controlling MDS X-Git-Tag: v4.1.12-124.31.3~187 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=9948f836572f9273013e5e62e2dfabdbd26145b7;p=users%2Fjedix%2Flinux-maple.git x86/speculation/mds: Add debugfs for controlling MDS Add debugfs entries for controlling mds_user_clear and mds_idle_clear static keys which would enable the mitigation in the respective paths. Orabug: 29526900 CVE: CVE-2018-12126 CVE: CVE-2018-12130 CVE: CVE-2018-12127 Signed-off-by: Kanth Ghatraju Reviewed-by: Mihai Carabas Reviewed-by: Boris Ostrovsky --- diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index fe7e5df41236..0c86d0aa513a 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -1021,6 +1021,13 @@ enum l1tf_mitigations { extern enum l1tf_mitigations l1tf_mitigation; +extern void mds_idle_clear_enable(void); +extern void mds_idle_clear_disable(void); +extern void mds_user_clear_enable(void); +extern void mds_user_clear_disable(void); +extern bool mds_user_clear_enabled(void); +extern bool mds_idle_clear_enabled(void); + enum mds_mitigations { MDS_MITIGATION_OFF, MDS_MITIGATION_FULL, diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile index 3a2f88bb33c1..949e766ca7f7 100644 --- a/arch/x86/kernel/cpu/Makefile +++ b/arch/x86/kernel/cpu/Makefile @@ -17,6 +17,7 @@ obj-y += common.o obj-y += rdrand.o obj-y += match.o obj-y += spec_ctrl.o +obj-y += mds_ctrl.o obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_X86_FEATURE_NAMES) += capflags.o powerflags.o diff --git a/arch/x86/kernel/cpu/bugs_64.c b/arch/x86/kernel/cpu/bugs_64.c index 7babe5d1c4b2..82c1506caf96 100644 --- a/arch/x86/kernel/cpu/bugs_64.c +++ b/arch/x86/kernel/cpu/bugs_64.c @@ -1287,6 +1287,36 @@ static void __init l1tf_select_mitigation(void) #undef pr_fmt #define pr_fmt(fmt) "MDS: " fmt +bool mds_user_clear_enabled(void) +{ + return static_key_enabled(&mds_user_clear); +} + +void mds_user_clear_enable(void) +{ + static_branch_enable(&mds_user_clear); +} + +void mds_user_clear_disable(void) +{ + static_branch_disable(&mds_user_clear); +} + +bool mds_idle_clear_enabled(void) +{ + return static_key_enabled(&mds_idle_clear); +} + +void mds_idle_clear_enable(void) +{ + static_branch_enable(&mds_idle_clear); +} + +void mds_idle_clear_disable(void) +{ + static_branch_disable(&mds_idle_clear); +} + /* Default mitigation for L1TF-affected CPUs */ static enum mds_mitigations mds_mitigation __read_mostly = MDS_MITIGATION_FULL; diff --git a/arch/x86/kernel/cpu/mds_ctrl.c b/arch/x86/kernel/cpu/mds_ctrl.c new file mode 100644 index 000000000000..604b37969f5a --- /dev/null +++ b/arch/x86/kernel/cpu/mds_ctrl.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +static ssize_t __enabled_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos, unsigned int *field) +{ + char buf[2] = {'0', '\n'};; + + if (*field) + buf[0] = '1'; + + return simple_read_from_buffer(user_buf, count, ppos, buf, 2); +} + +static ssize_t mds_key_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos, + bool (*enabled_func) (void)) +{ + u32 sysctl_mds_key = (*enabled_func)() ? 1 : 0; + + return __enabled_read(file, user_buf, count, ppos, + &sysctl_mds_key); +} + +static ssize_t mds_key_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos, + void (*enable_func) (void), + void (*disable_func) (void)) +{ + char buf[2]; + ssize_t len = 1; + unsigned int enable; + + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + buf[len] = '\0'; + if (kstrtouint(buf, 0, &enable)) + return -EINVAL; + + /* Only 0 and 1 are allowed */ + if (enable > 1) + return -EINVAL; + + if (enable) + (*enable_func)(); + else + (*disable_func)(); + + return count; +} + +static ssize_t mds_idle_clear_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + return mds_key_read(file, user_buf, count, ppos, + mds_idle_clear_enabled); +} + +static ssize_t mds_user_clear_read(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + return mds_key_read(file, user_buf, count, ppos, + mds_user_clear_enabled); +} + +static ssize_t mds_user_clear_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + return mds_key_write(file, user_buf, count, ppos, + mds_user_clear_enable, + mds_user_clear_disable); +} + +static ssize_t mds_idle_clear_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + return mds_key_write(file, user_buf, count, ppos, + mds_idle_clear_enable, + mds_idle_clear_disable); +} + +static const struct file_operations fops_mds_user_clear = { + .read = mds_user_clear_read, + .write = mds_user_clear_write, + .llseek = default_llseek, +}; + +static const struct file_operations fops_mds_idle_clear = { + .read = mds_idle_clear_read, + .write = mds_idle_clear_write, + .llseek = default_llseek, +}; + +static int __init debugfs_mds_ctrl(void) +{ + debugfs_create_file("mds_user_clear", + 0600, arch_debugfs_dir, NULL, + &fops_mds_user_clear); + debugfs_create_file("mds_idle_clear", + 0600, arch_debugfs_dir, NULL, + &fops_mds_idle_clear); + return 0; +} + +late_initcall(debugfs_mds_ctrl);