]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/vmscape: Enable the mitigation
authorPawan Gupta <pawan.kumar.gupta@linux.intel.com>
Thu, 14 Aug 2025 17:20:42 +0000 (10:20 -0700)
committerDave Hansen <dave.hansen@linux.intel.com>
Thu, 14 Aug 2025 17:37:33 +0000 (10:37 -0700)
Enable the previously added mitigation for VMscape. Add the cmdline
vmscape={off|ibpb|force} and sysfs reporting.

Signed-off-by: Pawan Gupta <pawan.kumar.gupta@linux.intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Dave Hansen <dave.hansen@linux.intel.com>
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/admin-guide/kernel-parameters.txt
arch/x86/Kconfig
arch/x86/kernel/cpu/bugs.c
drivers/base/cpu.c
include/linux/cpu.h

index ab8cd337f43aaddbfa21bcd42b52448eb5bf65c2..8aed6d94c4cd0d406627f54962df225629c1863c 100644 (file)
@@ -586,6 +586,7 @@ What:               /sys/devices/system/cpu/vulnerabilities
                /sys/devices/system/cpu/vulnerabilities/srbds
                /sys/devices/system/cpu/vulnerabilities/tsa
                /sys/devices/system/cpu/vulnerabilities/tsx_async_abort
+               /sys/devices/system/cpu/vulnerabilities/vmscape
 Date:          January 2018
 Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
 Description:   Information about CPU vulnerabilities
index 747a55abf4946bb9efe320f0f62fdcd1560b0a71..5a7a83c411e9c526f8df6d28beb4c784aec3cac9 100644 (file)
                                               srbds=off [X86,INTEL]
                                               ssbd=force-off [ARM64]
                                               tsx_async_abort=off [X86]
+                                              vmscape=off [X86]
 
                                Exceptions:
                                               This does not have any effect on
        vmpoff=         [KNL,S390] Perform z/VM CP command after power off.
                        Format: <command>
 
+       vmscape=        [X86] Controls mitigation for VMscape attacks.
+                       VMscape attacks can leak information from a userspace
+                       hypervisor to a guest via speculative side-channels.
+
+                       off             - disable the mitigation
+                       ibpb            - use Indirect Branch Prediction Barrier
+                                         (IBPB) mitigation (default)
+                       force           - force vulnerability detection even on
+                                         unaffected processors
+
        vsyscall=       [X86-64,EARLY]
                        Controls the behavior of vsyscalls (i.e. calls to
                        fixed addresses of 0xffffffffff600x00 from legacy
index 58d890fe2100eb6990880bcf5ba600cdefb0a7d1..52c8910ba2efddffd6ff2e218288043700f327e2 100644 (file)
@@ -2701,6 +2701,15 @@ config MITIGATION_TSA
          security vulnerability on AMD CPUs which can lead to forwarding of
          invalid info to subsequent instructions and thus can affect their
          timing and thereby cause a leakage.
+
+config MITIGATION_VMSCAPE
+       bool "Mitigate VMSCAPE"
+       depends on KVM
+       default y
+       help
+         Enable mitigation for VMSCAPE attacks. VMSCAPE is a hardware security
+         vulnerability on Intel and AMD CPUs that may allow a guest to do
+         Spectre v2 style attacks on userspace hypervisor.
 endif
 
 config ARCH_HAS_ADD_PAGES
index 410f8df8b77a1a78e58c68d6e357e9b13edc6a51..c81024dfc4c868c77d583d9ab4de247ceaa31987 100644 (file)
@@ -96,6 +96,9 @@ static void __init its_update_mitigation(void);
 static void __init its_apply_mitigation(void);
 static void __init tsa_select_mitigation(void);
 static void __init tsa_apply_mitigation(void);
+static void __init vmscape_select_mitigation(void);
+static void __init vmscape_update_mitigation(void);
+static void __init vmscape_apply_mitigation(void);
 
 /* The base value of the SPEC_CTRL MSR without task-specific bits set */
 u64 x86_spec_ctrl_base;
@@ -270,6 +273,7 @@ void __init cpu_select_mitigations(void)
        its_select_mitigation();
        bhi_select_mitigation();
        tsa_select_mitigation();
+       vmscape_select_mitigation();
 
        /*
         * After mitigations are selected, some may need to update their
@@ -301,6 +305,7 @@ void __init cpu_select_mitigations(void)
        bhi_update_mitigation();
        /* srso_update_mitigation() depends on retbleed_update_mitigation(). */
        srso_update_mitigation();
+       vmscape_update_mitigation();
 
        spectre_v1_apply_mitigation();
        spectre_v2_apply_mitigation();
@@ -318,6 +323,7 @@ void __init cpu_select_mitigations(void)
        its_apply_mitigation();
        bhi_apply_mitigation();
        tsa_apply_mitigation();
+       vmscape_apply_mitigation();
 }
 
 /*
@@ -3322,6 +3328,77 @@ static void __init srso_apply_mitigation(void)
        }
 }
 
+#undef pr_fmt
+#define pr_fmt(fmt)    "VMSCAPE: " fmt
+
+enum vmscape_mitigations {
+       VMSCAPE_MITIGATION_NONE,
+       VMSCAPE_MITIGATION_AUTO,
+       VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER,
+       VMSCAPE_MITIGATION_IBPB_ON_VMEXIT,
+};
+
+static const char * const vmscape_strings[] = {
+       [VMSCAPE_MITIGATION_NONE]               = "Vulnerable",
+       /* [VMSCAPE_MITIGATION_AUTO] */
+       [VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER]  = "Mitigation: IBPB before exit to userspace",
+       [VMSCAPE_MITIGATION_IBPB_ON_VMEXIT]     = "Mitigation: IBPB on VMEXIT",
+};
+
+static enum vmscape_mitigations vmscape_mitigation __ro_after_init =
+       IS_ENABLED(CONFIG_MITIGATION_VMSCAPE) ? VMSCAPE_MITIGATION_AUTO : VMSCAPE_MITIGATION_NONE;
+
+static int __init vmscape_parse_cmdline(char *str)
+{
+       if (!str)
+               return -EINVAL;
+
+       if (!strcmp(str, "off")) {
+               vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
+       } else if (!strcmp(str, "ibpb")) {
+               vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER;
+       } else if (!strcmp(str, "force")) {
+               setup_force_cpu_bug(X86_BUG_VMSCAPE);
+               vmscape_mitigation = VMSCAPE_MITIGATION_AUTO;
+       } else {
+               pr_err("Ignoring unknown vmscape=%s option.\n", str);
+       }
+
+       return 0;
+}
+early_param("vmscape", vmscape_parse_cmdline);
+
+static void __init vmscape_select_mitigation(void)
+{
+       if (cpu_mitigations_off() ||
+           !boot_cpu_has_bug(X86_BUG_VMSCAPE) ||
+           !boot_cpu_has(X86_FEATURE_IBPB)) {
+               vmscape_mitigation = VMSCAPE_MITIGATION_NONE;
+               return;
+       }
+
+       if (vmscape_mitigation == VMSCAPE_MITIGATION_AUTO)
+               vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER;
+}
+
+static void __init vmscape_update_mitigation(void)
+{
+       if (!boot_cpu_has_bug(X86_BUG_VMSCAPE))
+               return;
+
+       if (retbleed_mitigation == RETBLEED_MITIGATION_IBPB ||
+           srso_mitigation == SRSO_MITIGATION_IBPB_ON_VMEXIT)
+               vmscape_mitigation = VMSCAPE_MITIGATION_IBPB_ON_VMEXIT;
+
+       pr_info("%s\n", vmscape_strings[vmscape_mitigation]);
+}
+
+static void __init vmscape_apply_mitigation(void)
+{
+       if (vmscape_mitigation == VMSCAPE_MITIGATION_IBPB_EXIT_TO_USER)
+               setup_force_cpu_cap(X86_FEATURE_IBPB_EXIT_TO_USER);
+}
+
 #undef pr_fmt
 #define pr_fmt(fmt) fmt
 
@@ -3570,6 +3647,11 @@ static ssize_t tsa_show_state(char *buf)
        return sysfs_emit(buf, "%s\n", tsa_strings[tsa_mitigation]);
 }
 
+static ssize_t vmscape_show_state(char *buf)
+{
+       return sysfs_emit(buf, "%s\n", vmscape_strings[vmscape_mitigation]);
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
                               char *buf, unsigned int bug)
 {
@@ -3636,6 +3718,9 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
        case X86_BUG_TSA:
                return tsa_show_state(buf);
 
+       case X86_BUG_VMSCAPE:
+               return vmscape_show_state(buf);
+
        default:
                break;
        }
@@ -3727,6 +3812,11 @@ ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *bu
 {
        return cpu_show_common(dev, attr, buf, X86_BUG_TSA);
 }
+
+ssize_t cpu_show_vmscape(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       return cpu_show_common(dev, attr, buf, X86_BUG_VMSCAPE);
+}
 #endif
 
 void __warn_thunk(void)
index efc575a00edda96cd579528ef2d6080f52d4e812..008da0354fba35f6cefbc17cc7b291b5938d96ce 100644 (file)
@@ -603,6 +603,7 @@ CPU_SHOW_VULN_FALLBACK(ghostwrite);
 CPU_SHOW_VULN_FALLBACK(old_microcode);
 CPU_SHOW_VULN_FALLBACK(indirect_target_selection);
 CPU_SHOW_VULN_FALLBACK(tsa);
+CPU_SHOW_VULN_FALLBACK(vmscape);
 
 static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
 static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
@@ -622,6 +623,7 @@ static DEVICE_ATTR(ghostwrite, 0444, cpu_show_ghostwrite, NULL);
 static DEVICE_ATTR(old_microcode, 0444, cpu_show_old_microcode, NULL);
 static DEVICE_ATTR(indirect_target_selection, 0444, cpu_show_indirect_target_selection, NULL);
 static DEVICE_ATTR(tsa, 0444, cpu_show_tsa, NULL);
+static DEVICE_ATTR(vmscape, 0444, cpu_show_vmscape, NULL);
 
 static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_meltdown.attr,
@@ -642,6 +644,7 @@ static struct attribute *cpu_root_vulnerabilities_attrs[] = {
        &dev_attr_old_microcode.attr,
        &dev_attr_indirect_target_selection.attr,
        &dev_attr_tsa.attr,
+       &dev_attr_vmscape.attr,
        NULL
 };
 
index b91b993f58ee7f783325f17c7818bac600eccf72..487b3bf2e1eaf7899027f79b32bd9add58cc1a44 100644 (file)
@@ -83,6 +83,7 @@ extern ssize_t cpu_show_old_microcode(struct device *dev,
 extern ssize_t cpu_show_indirect_target_selection(struct device *dev,
                                                  struct device_attribute *attr, char *buf);
 extern ssize_t cpu_show_tsa(struct device *dev, struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_vmscape(struct device *dev, struct device_attribute *attr, char *buf);
 
 extern __printf(4, 5)
 struct device *cpu_device_create(struct device *parent, void *drvdata,