Blob Blame History Raw
From 9479630a09a7484c5b35a5c5eb89e6971d528d9e Mon Sep 17 00:00:00 2001
From: Julien Thierry <jthierry@redhat.com>
Date: Fri, 19 Jun 2020 08:13:25 +0100
Subject: [PATCH] x86/speculation: Prevent rogue cross-process SSBD shutdown

Kernels:
4.18.0-193.el8
4.18.0-193.1.2.el8_2
4.18.0-193.6.3.el8_2

Changes since last build:
arches: x86_64
process.o: changed function: __switch_to_xtra
process.o: changed function: speculation_ctrl_update
---------------------------

Modifications:
switch_to_cond_stibp jump label fix

commit e771c60266443edd15f3ebd0866a1ef6f070ebdc
Author: Waiman Long <longman@redhat.com>
Date:   Thu Jun 18 13:40:39 2020 +0100

    x86/speculation: Prevent rogue cross-process SSBD shutdown

    Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1847357
    CVE: CVE-2020-10766

    commit dbbe2ad02e9df26e372f38cc3e70dab9222c832e
    Author: Anthony Steinhauser <asteinhauser@google.com>
    Date:   Sun, 5 Jan 2020 12:19:43 -0800

        x86/speculation: Prevent rogue cross-process SSBD shutdown

        On context switch the change of TIF_SSBD and TIF_SPEC_IB are evaluated
        to adjust the mitigations accordingly. This is optimized to avoid the
        expensive MSR write if not needed.

        This optimization is buggy and allows an attacker to shutdown the SSBD
        protection of a victim process.

        The update logic reads the cached base value for the speculation control
        MSR which has neither the SSBD nor the STIBP bit set. It then OR's the
        SSBD bit only when TIF_SSBD is different and requests the MSR update.

        That means if TIF_SSBD of the previous and next task are the same, then
        the base value is not updated, even if TIF_SSBD is set. The MSR write is
        not requested.

        Subsequently if the TIF_STIBP bit differs then the STIBP bit is updated
        in the base value and the MSR is written with a wrong SSBD value.

        This was introduced when the per task/process conditional STIPB
        switching was added on top of the existing SSBD switching.

        It is exploitable if the attacker creates a process which enforces SSBD
        and has the contrary value of STIBP than the victim process (i.e. if the
        victim process enforces STIBP, the attacker process must not enforce it;
        if the victim process does not enforce STIBP, the attacker process must
        enforce it) and schedule it on the same core as the victim process. If
        the victim runs after the attacker the victim becomes vulnerable to
        Spectre V4.

        To fix this, update the MSR value independent of the TIF_SSBD difference
        and dependent on the SSBD mitigation method available. This ensures that
        a subsequent STIPB initiated MSR write has the correct state of SSBD.

        [ tglx: Handle X86_FEATURE_VIRT_SSBD & X86_FEATURE_VIRT_SSBD correctly
                and massaged changelog ]

        Fixes: 5bfbe3ad5840 ("x86/speculation: Prepare for per task indirect branch speculation control")
        Signed-off-by: Anthony Steinhauser <asteinhauser@google.com>
        Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
        Cc: stable@vger.kernel.org

    Signed-off-by: Waiman Long <longman@redhat.com>

Signed-off-by: Julien Thierry <jthierry@redhat.com>
---
 arch/x86/kernel/process.c | 30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index e5c5b1d724ab..9410134a38a8 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -431,30 +431,22 @@ static __always_inline void __speculation_ctrl_update(unsigned long tifp,
 
 	lockdep_assert_irqs_disabled();
 
-	/*
-	 * If TIF_SSBD is different, select the proper mitigation
-	 * method. Note that if SSBD mitigation is disabled or permanentely
-	 * enabled this branch can't be taken because nothing can set
-	 * TIF_SSBD.
-	 */
-	if (tif_diff & _TIF_SSBD) {
-		if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) {
+	/* Handle change of TIF_SSBD depending on the mitigation method. */
+	if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) {
+		if (tif_diff & _TIF_SSBD)
 			amd_set_ssb_virt_state(tifn);
-		} else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) {
+	} else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) {
+		if (tif_diff & _TIF_SSBD)
 			amd_set_core_ssb_state(tifn);
-		} else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
-			   static_cpu_has(X86_FEATURE_AMD_SSBD)) {
-			msr |= ssbd_tif_to_spec_ctrl(tifn);
-			updmsr  = true;
-		}
+	} else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+		   static_cpu_has(X86_FEATURE_AMD_SSBD)) {
+		updmsr |= !!(tif_diff & _TIF_SSBD);
+		msr |= ssbd_tif_to_spec_ctrl(tifn);
 	}
 
-	/*
-	 * Only evaluate TIF_SPEC_IB if conditional STIBP is enabled,
-	 * otherwise avoid the MSR write.
-	 */
+	/* Only evaluate TIF_SPEC_IB if conditional STIBP is enabled. */
 	if (IS_ENABLED(CONFIG_SMP) &&
-	    static_branch_unlikely(&switch_to_cond_stibp)) {
+	    static_key_enabled(&switch_to_cond_stibp)) {
 		updmsr |= !!(tif_diff & _TIF_SPEC_IB);
 		msr |= stibp_tif_to_spec_ctrl(tifn);
 	}
-- 
2.21.3