x86/speculation: Allow enabling STIBP with legacy IBRS
authorKP Singh <kpsingh@kernel.org>
Mon, 27 Feb 2023 06:05:40 +0000 (07:05 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 10 Mar 2023 08:34:14 +0000 (09:34 +0100)
commit 6921ed9049bc7457f66c1596c5b78aec0dae4a9d upstream.

When plain IBRS is enabled (not enhanced IBRS), the logic in
spectre_v2_user_select_mitigation() determines that STIBP is not needed.

The IBRS bit implicitly protects against cross-thread branch target
injection. However, with legacy IBRS, the IBRS bit is cleared on
returning to userspace for performance reasons which leaves userspace
threads vulnerable to cross-thread branch target injection against which
STIBP protects.

Exclude IBRS from the spectre_v2_in_ibrs_mode() check to allow for
enabling STIBP (through seccomp/prctl() by default or always-on, if
selected by spectre_v2_user kernel cmdline parameter).

  [ bp: Massage. ]

Fixes: 7c693f54c873 ("x86/speculation: Add spectre_v2=ibrs option to support Kernel IBRS")
Reported-by: José Oliveira <joseloliveira11@gmail.com>
Reported-by: Rodrigo Branco <rodrigo@kernelhacking.com>
Signed-off-by: KP Singh <kpsingh@kernel.org>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20230220120127.1975241-1-kpsingh@kernel.org
Link: https://lore.kernel.org/r/20230221184908.2349578-1-kpsingh@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/x86/kernel/cpu/bugs.c

index c730b29..f549928 100644 (file)
@@ -1103,14 +1103,18 @@ spectre_v2_parse_user_cmdline(void)
        return SPECTRE_V2_USER_CMD_AUTO;
 }
 
-static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
+static inline bool spectre_v2_in_eibrs_mode(enum spectre_v2_mitigation mode)
 {
-       return mode == SPECTRE_V2_IBRS ||
-              mode == SPECTRE_V2_EIBRS ||
+       return mode == SPECTRE_V2_EIBRS ||
               mode == SPECTRE_V2_EIBRS_RETPOLINE ||
               mode == SPECTRE_V2_EIBRS_LFENCE;
 }
 
+static inline bool spectre_v2_in_ibrs_mode(enum spectre_v2_mitigation mode)
+{
+       return spectre_v2_in_eibrs_mode(mode) || mode == SPECTRE_V2_IBRS;
+}
+
 static void __init
 spectre_v2_user_select_mitigation(void)
 {
@@ -1173,12 +1177,19 @@ spectre_v2_user_select_mitigation(void)
        }
 
        /*
-        * If no STIBP, IBRS or enhanced IBRS is enabled, or SMT impossible,
-        * STIBP is not required.
+        * If no STIBP, enhanced IBRS is enabled, or SMT impossible, STIBP
+        * is not required.
+        *
+        * Enhanced IBRS also protects against cross-thread branch target
+        * injection in user-mode as the IBRS bit remains always set which
+        * implicitly enables cross-thread protections.  However, in legacy IBRS
+        * mode, the IBRS bit is set only on kernel entry and cleared on return
+        * to userspace. This disables the implicit cross-thread protection,
+        * so allow for STIBP to be selected in that case.
         */
        if (!boot_cpu_has(X86_FEATURE_STIBP) ||
            !smt_possible ||
-           spectre_v2_in_ibrs_mode(spectre_v2_enabled))
+           spectre_v2_in_eibrs_mode(spectre_v2_enabled))
                return;
 
        /*
@@ -2305,7 +2316,7 @@ static ssize_t mmio_stale_data_show_state(char *buf)
 
 static char *stibp_state(void)
 {
-       if (spectre_v2_in_ibrs_mode(spectre_v2_enabled))
+       if (spectre_v2_in_eibrs_mode(spectre_v2_enabled))
                return "";
 
        switch (spectre_v2_user_stibp) {