x86/speculation: Enable prctl mode for spectre_v2_user
authorThomas Gleixner <tglx@linutronix.de>
Sun, 25 Nov 2018 18:33:54 +0000 (19:33 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Dec 2018 18:41:22 +0000 (19:41 +0100)
commit 7cc765a67d8e04ef7d772425ca5a2a1e2b894c15 upstream

Now that all prerequisites are in place:

 - Add the prctl command line option

 - Default the 'auto' mode to 'prctl'

 - When SMT state changes, update the static key which controls the
   conditional STIBP evaluation on context switch.

 - At init update the static key which controls the conditional IBPB
   evaluation on context switch.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: David Woodhouse <dwmw@amazon.co.uk>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Casey Schaufler <casey.schaufler@intel.com>
Cc: Asit Mallick <asit.k.mallick@intel.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Jon Masters <jcm@redhat.com>
Cc: Waiman Long <longman9394@gmail.com>
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: Dave Stewart <david.c.stewart@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20181125185005.958421388@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Documentation/admin-guide/kernel-parameters.txt
arch/x86/kernel/cpu/bugs.c

index f0c19f61db8071a91d57a2c0410dfdbcd60b8467..dd9783e43443a6d5ea412e522c4c6f5a582ef64c 100644 (file)
                        off     - Unconditionally disable mitigations. Is
                                  enforced by spectre_v2=off
 
+                       prctl   - Indirect branch speculation is enabled,
+                                 but mitigation can be enabled via prctl
+                                 per thread.  The mitigation control state
+                                 is inherited on fork.
+
                        auto    - Kernel selects the mitigation depending on
                                  the available CPU features and vulnerability.
-                                 Default is off.
+                                 Default is prctl.
 
                        Not specifying this option is equivalent to
                        spectre_v2_user=auto.
index bcd39b928fea611a1ab122fd671b760f581d1317..d87a877b1b383020aa5c2aae4cfbd75779353340 100644 (file)
@@ -254,11 +254,13 @@ enum spectre_v2_user_cmd {
        SPECTRE_V2_USER_CMD_NONE,
        SPECTRE_V2_USER_CMD_AUTO,
        SPECTRE_V2_USER_CMD_FORCE,
+       SPECTRE_V2_USER_CMD_PRCTL,
 };
 
 static const char * const spectre_v2_user_strings[] = {
        [SPECTRE_V2_USER_NONE]          = "User space: Vulnerable",
        [SPECTRE_V2_USER_STRICT]        = "User space: Mitigation: STIBP protection",
+       [SPECTRE_V2_USER_PRCTL]         = "User space: Mitigation: STIBP via prctl",
 };
 
 static const struct {
@@ -269,6 +271,7 @@ static const struct {
        { "auto",       SPECTRE_V2_USER_CMD_AUTO,       false },
        { "off",        SPECTRE_V2_USER_CMD_NONE,       false },
        { "on",         SPECTRE_V2_USER_CMD_FORCE,      true  },
+       { "prctl",      SPECTRE_V2_USER_CMD_PRCTL,      false },
 };
 
 static void __init spec_v2_user_print_cond(const char *reason, bool secure)
@@ -323,12 +326,15 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
                smt_possible = false;
 
        switch (spectre_v2_parse_user_cmdline(v2_cmd)) {
-       case SPECTRE_V2_USER_CMD_AUTO:
        case SPECTRE_V2_USER_CMD_NONE:
                goto set_mode;
        case SPECTRE_V2_USER_CMD_FORCE:
                mode = SPECTRE_V2_USER_STRICT;
                break;
+       case SPECTRE_V2_USER_CMD_AUTO:
+       case SPECTRE_V2_USER_CMD_PRCTL:
+               mode = SPECTRE_V2_USER_PRCTL;
+               break;
        }
 
        /* Initialize Indirect Branch Prediction Barrier */
@@ -339,6 +345,9 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
                case SPECTRE_V2_USER_STRICT:
                        static_branch_enable(&switch_mm_always_ibpb);
                        break;
+               case SPECTRE_V2_USER_PRCTL:
+                       static_branch_enable(&switch_mm_cond_ibpb);
+                       break;
                default:
                        break;
                }
@@ -351,6 +360,12 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
        if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
                return;
 
+       /*
+        * If SMT is not possible or STIBP is not available clear the STIPB
+        * mode.
+        */
+       if (!smt_possible || !boot_cpu_has(X86_FEATURE_STIBP))
+               mode = SPECTRE_V2_USER_NONE;
 set_mode:
        spectre_v2_user = mode;
        /* Only print the STIBP mode when SMT possible */
@@ -549,6 +564,15 @@ static void update_stibp_strict(void)
        on_each_cpu(update_stibp_msr, NULL, 1);
 }
 
+/* Update the static key controlling the evaluation of TIF_SPEC_IB */
+static void update_indir_branch_cond(void)
+{
+       if (sched_smt_active())
+               static_branch_enable(&switch_to_cond_stibp);
+       else
+               static_branch_disable(&switch_to_cond_stibp);
+}
+
 void arch_smt_update(void)
 {
        /* Enhanced IBRS implies STIBP. No update required. */
@@ -564,6 +588,7 @@ void arch_smt_update(void)
                update_stibp_strict();
                break;
        case SPECTRE_V2_USER_PRCTL:
+               update_indir_branch_cond();
                break;
        }
 
@@ -1035,7 +1060,8 @@ static char *stibp_state(void)
        case SPECTRE_V2_USER_STRICT:
                return ", STIBP: forced";
        case SPECTRE_V2_USER_PRCTL:
-               return "";
+               if (static_key_enabled(&switch_to_cond_stibp))
+                       return ", STIBP: conditional";
        }
        return "";
 }
@@ -1043,14 +1069,11 @@ static char *stibp_state(void)
 static char *ibpb_state(void)
 {
        if (boot_cpu_has(X86_FEATURE_IBPB)) {
-               switch (spectre_v2_user) {
-               case SPECTRE_V2_USER_NONE:
-                       return ", IBPB: disabled";
-               case SPECTRE_V2_USER_STRICT:
+               if (static_key_enabled(&switch_mm_always_ibpb))
                        return ", IBPB: always-on";
-               case SPECTRE_V2_USER_PRCTL:
-                       return "";
-               }
+               if (static_key_enabled(&switch_mm_cond_ibpb))
+                       return ", IBPB: conditional";
+               return ", IBPB: disabled";
        }
        return "";
 }