[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging-4.17] x86/spec-ctrl: Synthesise ITS_NO to guests on unaffected hardware



commit 015a7e3ab2296f5b7f668537fb3fa3bb23f974c9
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Thu May 9 17:43:47 2024 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Mon May 12 17:32:24 2025 +0100

    x86/spec-ctrl: Synthesise ITS_NO to guests on unaffected hardware
    
    It is easier to express feature word 17 in terms of word 16 + [32, 64) as
    that's how the layout is given in documentation.
    
    This is part of XSA-469 / CVE-2024-28956
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    (cherry picked from commit f6042f38e621525feff86bb101dc751d2d87cff8)
---
 xen/arch/x86/include/asm/cpufeature.h       |  1 +
 xen/arch/x86/spec_ctrl.c                    | 86 +++++++++++++++++++++++++++++
 xen/include/public/arch-x86/cpufeatureset.h |  3 +-
 xen/tools/gen-cpuid.py                      |  2 +-
 4 files changed, 90 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/include/asm/cpufeature.h 
b/xen/arch/x86/include/asm/cpufeature.h
index a6b8af1296..d9aedfc25a 100644
--- a/xen/arch/x86/include/asm/cpufeature.h
+++ b/xen/arch/x86/include/asm/cpufeature.h
@@ -164,6 +164,7 @@
 #define cpu_has_gds_no          boot_cpu_has(X86_FEATURE_GDS_NO)
 #define cpu_has_rfds_no         boot_cpu_has(X86_FEATURE_RFDS_NO)
 #define cpu_has_rfds_clear      boot_cpu_has(X86_FEATURE_RFDS_CLEAR)
+#define cpu_has_its_no          boot_cpu_has(X86_FEATURE_ITS_NO)
 
 /* Synthesized. */
 #define cpu_has_arch_perfmon    boot_cpu_has(X86_FEATURE_ARCH_PERFMON)
diff --git a/xen/arch/x86/spec_ctrl.c b/xen/arch/x86/spec_ctrl.c
index 2f777e8a7e..559ee90b44 100644
--- a/xen/arch/x86/spec_ctrl.c
+++ b/xen/arch/x86/spec_ctrl.c
@@ -1766,6 +1766,90 @@ static void __init bhi_calculations(void)
     }
 }
 
+/*
+ * 
https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/indirect-target-selection.html
+ */
+static void __init its_calculations(void)
+{
+    /*
+     * Indirect Target Selection is a Branch Prediction bug whereby certain
+     * indirect branches (including RETs) get predicted using a direct branch
+     * target, rather than a suitable indirect target, bypassing hardware
+     * isolation protections.
+     *
+     * ITS affects Core (but not Atom) processors starting from the
+     * introduction of eIBRS, up to but not including Golden Cove cores
+     * (checked here with BHI_CTRL).
+     *
+     * The ITS_NO feature is not expected to be enumerated by hardware, and is
+     * only for VMMs to synthesise for guests.
+     *
+     * ITS comes in 3 flavours:
+     *
+     *   1) Across-IBPB.  Indirect branches after the IBPB can be controlled
+     *      by direct targets which existed prior to the IBPB.  This is
+     *      addressed in the IPU 2025.1 microcode drop, and has no other
+     *      software interaction.
+     *
+     *   2) Guest/Host.  Indirect branches in the VMM can be controlled by
+     *      direct targets from the guest.  This applies equally to PV guests
+     *      (Ring3) and HVM guests (VMX), and applies to all Skylake-uarch
+     *      cores with eIBRS.
+     *
+     *   3) Intra-mode.  Indirect branches in the VMM can be controlled by
+     *      other execution in the same mode.
+     */
+
+    /*
+     * If we can see ITS_NO, or we're virtualised, do nothing.  We are or may
+     * migrate somewhere unsafe.
+     */
+    if ( cpu_has_its_no || cpu_has_hypervisor )
+        return;
+
+    /* ITS is only known to affect Intel processors at this time. */
+    if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
+        return;
+
+    /*
+     * ITS does not exist on:
+     *  - non-Family 6 CPUs
+     *  - those without eIBRS
+     *  - those with BHI_CTRL
+     * but we still need to synthesise ITS_NO.
+     */
+    if ( boot_cpu_data.x86 != 6 || !cpu_has_eibrs ||
+         boot_cpu_has(X86_FEATURE_BHI_CTRL) )
+        goto synthesise;
+
+    switch ( boot_cpu_data.x86_model )
+    {
+        /* These Skylake-uarch cores suffer cases #2 and #3. */
+    case INTEL_FAM6_SKYLAKE_X:
+    case INTEL_FAM6_KABYLAKE_L:
+    case INTEL_FAM6_KABYLAKE:
+    case INTEL_FAM6_COMETLAKE:
+    case INTEL_FAM6_COMETLAKE_L:
+        return;
+
+        /* These Sunny/Willow/Cypress Cove cores suffer case #3. */
+    case INTEL_FAM6_ICELAKE_X:
+    case INTEL_FAM6_ICELAKE_D:
+    case INTEL_FAM6_ICELAKE_L:
+    case INTEL_FAM6_TIGERLAKE_L:
+    case INTEL_FAM6_TIGERLAKE:
+    case INTEL_FAM6_ROCKETLAKE:
+        return;
+
+    default:
+        break;
+    }
+
+    /* Platforms remaining are not believed to be vulnerable to ITS. */
+ synthesise:
+    setup_force_cpu_cap(X86_FEATURE_ITS_NO);
+}
+
 void spec_ctrl_init_domain(struct domain *d)
 {
     bool pv = is_pv_domain(d);
@@ -2316,6 +2400,8 @@ void __init init_speculation_mitigations(void)
 
     bhi_calculations();
 
+    its_calculations();
+
     print_details(thunk);
 
     /*
diff --git a/xen/include/public/arch-x86/cpufeatureset.h 
b/xen/include/public/arch-x86/cpufeatureset.h
index 0004fd4bf5..99c4dc1ffd 100644
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -334,7 +334,8 @@ XEN_CPUFEATURE(GDS_NO,             16*32+26) /*A  No Gather 
Data Sampling */
 XEN_CPUFEATURE(RFDS_NO,            16*32+27) /*A  No Register File Data 
Sampling */
 XEN_CPUFEATURE(RFDS_CLEAR,         16*32+28) /*!A Register File(s) cleared by 
VERW */
 
-/* Intel-defined CPU features, MSR_ARCH_CAPS 0x10a.edx, word 17 */
+/* Intel-defined CPU features, MSR_ARCH_CAPS 0x10a.edx, word 17 (express in 
terms of word 16) */
+XEN_CPUFEATURE(ITS_NO,             16*32+62) /*!A No Indirect Target Selection 
*/
 
 #endif /* XEN_CPUFEATURE */
 
diff --git a/xen/tools/gen-cpuid.py b/xen/tools/gen-cpuid.py
index 415b8b1d68..05b1c13ec4 100755
--- a/xen/tools/gen-cpuid.py
+++ b/xen/tools/gen-cpuid.py
@@ -51,7 +51,7 @@ def parse_definitions(state):
         r"\s+/\*([\w!]*) .*$")
 
     word_regex = re.compile(
-        r"^/\* .* word (\d*) \*/$")
+        r"^/\* .* word (\d*) .*\*/$")
     last_word = -1
 
     this = sys.modules[__name__]
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.17



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.