From: Alexandre Chartre Date: Tue, 4 Sep 2018 12:51:23 +0000 (+0200) Subject: x86/speculation: Add sysfs entry to enable/disable retpoline X-Git-Tag: v4.1.12-124.31.3~461 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=11ecaece218962b57966c3997860e8bf92f4efea;p=users%2Fjedix%2Flinux-maple.git x86/speculation: Add sysfs entry to enable/disable retpoline Add /sys/kernel/debug/x86/retpoline_enabled to enable/disable retpoline. Enabling retpoline will also enable IBRS for the firmware. Note that IBRS and retpoline can't be enabled together. Enabling retpoline while IBRS is already enabled will automatically disable IBRS. Similarly, enabling IBRS while retpoline is already enabled will automatically disable retpoline. On Skylake, retpoline is not provided and can't be enabled unless the system has been explicitly booted with retpoline (using spectre_v2=retpoline or spectre_v2_heuristics=skylake=off). Also fix the behavior when retpoline is not available (!CONFIG_RETPOLINE): now we will try using IBRS (if it is available) instead of not using any mitigation. Signed-off-by: Alexandre Chartre Reviewed-by: Mihai Carabas (cherry picked from UEK5 commit d75554157882d9b4df91f0b2bbc4907e2731781e) [Backport: a large part of d75554157882d9b4df91f0b2bbc4907e2731781e was already ported in previous commit ("x86/speculation: switch to IBRS when loading a non-retpoline module"). This ports the remaining part which effectively adds the retpoline_enabled sysfs entry. Also we issue a warning when enabling retpoline and a non-retpoline module is loaded.] Orabug: 28607548 Signed-off-by: Alexandre Chartre Reviewed-by: Darren Kenny Reviewed-by: Mihai Carabas Reviewed-by: Boris Ostrovsky Signed-off-by: Brian Maly --- diff --git a/arch/x86/kernel/cpu/spec_ctrl.c b/arch/x86/kernel/cpu/spec_ctrl.c index e7c2d052d37a9..ad0958166f359 100644 --- a/arch/x86/kernel/cpu/spec_ctrl.c +++ b/arch/x86/kernel/cpu/spec_ctrl.c @@ -43,14 +43,9 @@ static ssize_t ibrs_enabled_write(struct file *file, if (!ibrs_supported) return -ENODEV; - if (retpoline_enabled()) { - pr_warn("retpoline is enabled. Ignoring request to change ibrs state.\n"); - return -EINVAL; - } - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; buf[len] = '\0'; if (kstrtouint(buf, 0, &enable)) @@ -175,6 +170,66 @@ static const struct file_operations fops_retpoline_fallback = { .llseek = default_llseek, }; +#ifdef CONFIG_RETPOLINE + +static ssize_t retpoline_enabled_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + u32 sysctl_retpoline_enabled = retpoline_enabled() ? 1 : 0; + + return __enabled_read(file, user_buf, count, ppos, + &sysctl_retpoline_enabled); +} + +static ssize_t retpoline_enabled_write(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + char buf[32]; + ssize_t len; + unsigned int enable; + + len = min(count, sizeof(buf) - 1); + 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; + + /* + * The retpoline feature is always present except on Skylake + * if the system wasn't explicitly booted with retpoline. + */ + if (enable && !boot_cpu_has(X86_FEATURE_RETPOLINE)) { + pr_warn("Retpoline is disabled by default on Skylake-generation system.\n"); + pr_warn("Use the 'spectre_v2=retpoline' parameter to boot with retpoline.\n"); + return -EINVAL; + } + + if (enable) { + if (test_taint(TAINT_NO_RETPOLINE)) + pr_warn("Enabling retpoline with a module not compiled with retpoline compiler.\n"); + change_spectre_v2_mitigation(SPECTRE_V2_ENABLE_RETPOLINE); + } else { + change_spectre_v2_mitigation(SPECTRE_V2_DISABLE_RETPOLINE); + } + + return count; +} + +static const struct file_operations fops_retpoline_enabled = { + .read = retpoline_enabled_read, + .write = retpoline_enabled_write, + .llseek = default_llseek, +}; + +#endif /* CONFIG_RETPOLINE */ + static int __init debugfs_spec_ctrl(void) { debugfs_create_file("ibrs_enabled", S_IRUSR | S_IWUSR, @@ -183,6 +238,11 @@ static int __init debugfs_spec_ctrl(void) arch_debugfs_dir, NULL, &fops_ibpb_enabled); debugfs_create_file("retpoline_fallback", S_IRUSR | S_IWUSR, arch_debugfs_dir, NULL, &fops_retpoline_fallback); + if (IS_ENABLED(CONFIG_RETPOLINE)) { + debugfs_create_file("retpoline_enabled", + 0600, arch_debugfs_dir, NULL, + &fops_retpoline_enabled); + } return 0; } late_initcall(debugfs_spec_ctrl);