Bug 1430053 - Add prefs for index masking Spectre mitigations. r=luke,mccr8
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 18 Jan 2018 13:19:41 +0100
changeset 399810 a98f615965d73f6462924188fc2b1f2a620337bb
parent 399809 71516540db51fd17d6d938ea224c3231fe636fd5
child 399811 4dc616cbbb203e6b36ae21507359e70481a25919
push id99029
push userjandemooij@gmail.com
push dateThu, 18 Jan 2018 12:22:01 +0000
treeherdermozilla-inbound@4dc616cbbb20 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke, mccr8
bugs1430053
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1430053 - Add prefs for index masking Spectre mitigations. r=luke,mccr8
dom/ipc/ContentPrefs.cpp
js/src/jit/JitOptions.cpp
js/src/jit/JitOptions.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/shell/js.cpp
js/xpconnect/src/XPCJSContext.cpp
modules/libpref/init/all.js
--- a/dom/ipc/ContentPrefs.cpp
+++ b/dom/ipc/ContentPrefs.cpp
@@ -119,16 +119,17 @@ const char* mozilla::dom::ContentPrefs::
   "javascript.options.ion",
   "javascript.options.ion.offthread_compilation",
   "javascript.options.ion.threshold",
   "javascript.options.ion.unsafe_eager_compilation",
   "javascript.options.jit.full_debug_checks",
   "javascript.options.native_regexp",
   "javascript.options.parallel_parsing",
   "javascript.options.shared_memory",
+  "javascript.options.spectre.index_masking",
   "javascript.options.streams",
   "javascript.options.strict",
   "javascript.options.strict.debug",
   "javascript.options.throw_on_asmjs_validation_failure",
   "javascript.options.throw_on_debuggee_would_run",
   "javascript.options.wasm",
   "javascript.options.wasm_baselinejit",
   "javascript.options.wasm_ionjit",
--- a/js/src/jit/JitOptions.cpp
+++ b/js/src/jit/JitOptions.cpp
@@ -227,16 +227,18 @@ DefaultJitOptions::DefaultJitOptions()
     // pass decide.
     const char* forcedRegisterAllocatorEnv = "JIT_OPTION_forcedRegisterAllocator";
     if (const char* env = getenv(forcedRegisterAllocatorEnv)) {
         forcedRegisterAllocator = LookupRegisterAllocator(env);
         if (!forcedRegisterAllocator.isSome())
             Warn(forcedRegisterAllocatorEnv, env);
     }
 
+    SET_DEFAULT(spectreIndexMasking, false);
+
     // Toggles whether unboxed plain objects can be created by the VM.
     SET_DEFAULT(disableUnboxedObjects, false);
 
     // Test whether Atomics are allowed in asm.js code.
     SET_DEFAULT(asmJSAtomicsEnable, false);
 
     // Toggles the optimization whereby offsets are folded into loads and not
     // included in the bounds check.
--- a/js/src/jit/JitOptions.h
+++ b/js/src/jit/JitOptions.h
@@ -89,16 +89,18 @@ struct DefaultJitOptions
     uint32_t branchPruningEffectfulInstFactor;
     uint32_t branchPruningThreshold;
     uint32_t wasmBatchIonThreshold;
     uint32_t wasmBatchBaselineThreshold;
     mozilla::Maybe<uint32_t> forcedDefaultIonWarmUpThreshold;
     mozilla::Maybe<uint32_t> forcedDefaultIonSmallFunctionWarmUpThreshold;
     mozilla::Maybe<IonRegisterAllocator> forcedRegisterAllocator;
 
+    bool spectreIndexMasking;
+
     // The options below affect the rest of the VM, and not just the JIT.
     bool disableUnboxedObjects;
 
     DefaultJitOptions();
     bool isSmallFunction(JSScript* script) const;
     void setEagerCompilation();
     void setCompilerWarmUpThreshold(uint32_t warmUpThreshold);
     void resetCompilerWarmUpThreshold();
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -7218,16 +7218,19 @@ JS_SetGlobalJitCompilerOption(JSContext*
             jit::DefaultJitOptions defaultValues;
             value = defaultValues.jumpThreshold;
         }
         jit::JitOptions.jumpThreshold = value;
         break;
       case JSJITCOMPILER_SIMULATOR_ALWAYS_INTERRUPT:
         jit::JitOptions.simulatorAlwaysInterrupt = !!value;
         break;
+      case JSJITCOMPILER_SPECTRE_INDEX_MASKING:
+        jit::JitOptions.spectreIndexMasking = !!value;
+        break;
       case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE:
         jit::JitOptions.asmJSAtomicsEnable = !!value;
         break;
       case JSJITCOMPILER_WASM_FOLD_OFFSETS:
         jit::JitOptions.wasmFoldOffsets = !!value;
         break;
       case JSJITCOMPILER_ION_INTERRUPT_WITHOUT_SIGNAL:
         jit::JitOptions.ionInterruptWithoutSignals = !!value;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -5876,16 +5876,17 @@ JS_SetOffthreadIonCompilationEnabled(JSC
     Register(ION_ENABLE, "ion.enable")                                      \
     Register(ION_INTERRUPT_WITHOUT_SIGNAL, "ion.interrupt-without-signals") \
     Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis")          \
     Register(BASELINE_ENABLE, "baseline.enable")                            \
     Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable")  \
     Register(FULL_DEBUG_CHECKS, "jit.full-debug-checks")                    \
     Register(JUMP_THRESHOLD, "jump-threshold")                              \
     Register(SIMULATOR_ALWAYS_INTERRUPT, "simulator.always-interrupt")      \
+    Register(SPECTRE_INDEX_MASKING, "spectre.index-masking")                \
     Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable")                  \
     Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets")
 
 typedef enum JSJitCompilerOption {
 #define JIT_COMPILER_DECLARE(key, str) \
     JSJITCOMPILER_ ## key,
 
     JIT_COMPILER_OPTIONS(JIT_COMPILER_DECLARE)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -8363,16 +8363,25 @@ SetContextOptions(JSContext* cx, const O
         if (strcmp(str, "on") == 0)
             jit::JitOptions.disableCacheIR = false;
         else if (strcmp(str, "off") == 0)
             jit::JitOptions.disableCacheIR = true;
         else
             return OptionFailure("cache-ir-stubs", str);
     }
 
+    if (const char* str = op.getStringOption("spectre-mitigations")) {
+        if (strcmp(str, "on") == 0)
+            jit::JitOptions.spectreIndexMasking = true;
+        else if (strcmp(str, "off") == 0)
+            jit::JitOptions.spectreIndexMasking = false;
+        else
+            return OptionFailure("spectre-mitigations", str);
+    }
+
     if (const char* str = op.getStringOption("ion-scalar-replacement")) {
         if (strcmp(str, "on") == 0)
             jit::JitOptions.disableScalarReplacement = false;
         else if (strcmp(str, "off") == 0)
             jit::JitOptions.disableScalarReplacement = true;
         else
             return OptionFailure("ion-scalar-replacement", str);
     }
@@ -8881,16 +8890,18 @@ main(int argc, char** argv, char** envp)
                                "SharedArrayBuffer and Atomics "
 #  if SHARED_MEMORY_DEFAULT
                                "(default: on, off to disable)"
 #  else
                                "(default: off, on to enable)"
 #  endif
             )
 #endif
+        || !op.addStringOption('\0', "spectre-mitigations", "on/off",
+                               "Whether Spectre mitigations are enabled (default: off, on to enable)")
         || !op.addStringOption('\0', "cache-ir-stubs", "on/off",
                                "Use CacheIR stubs (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-shared-stubs", "on/off",
                                "Use shared stubs (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-scalar-replacement", "on/off",
                                "Scalar Replacement (default: on, off to disable)")
         || !op.addStringOption('\0', "ion-gvn", "[mode]",
                                "Specify Ion global value numbering:\n"
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -803,16 +803,18 @@ ReloadPrefsCallback(const char* pref, vo
                                                             "dump_stack_on_debuggee_would_run");
 
     bool werror = Preferences::GetBool(JS_OPTIONS_DOT_STR "werror");
 
     bool extraWarnings = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict");
 
     bool streams = Preferences::GetBool(JS_OPTIONS_DOT_STR "streams");
 
+    bool spectreIndexMasking = Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.index_masking");
+
     sSharedMemoryEnabled = Preferences::GetBool(JS_OPTIONS_DOT_STR "shared_memory");
 
 #ifdef DEBUG
     sExtraWarningsForSystemJS = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict.debug");
 #endif
 
 #ifdef JS_GC_ZEAL
     int32_t zeal = Preferences::GetInt(JS_OPTIONS_DOT_STR "gczeal", -1);
@@ -859,16 +861,18 @@ ReloadPrefsCallback(const char* pref, vo
     JS_SetOffthreadIonCompilationEnabled(cx, offthreadIonCompilation);
     JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_BASELINE_WARMUP_TRIGGER,
                                   useBaselineEager ? 0 : baselineThreshold);
     JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_WARMUP_TRIGGER,
                                   useIonEager ? 0 : ionThreshold);
 #ifdef DEBUG
     JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_FULL_DEBUG_CHECKS, fullJitDebugChecks);
 #endif
+
+    JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_INDEX_MASKING, spectreIndexMasking);
 }
 
 XPCJSContext::~XPCJSContext()
 {
     MOZ_COUNT_DTOR_INHERITED(XPCJSContext, CycleCollectedJSContext);
     // Elsewhere we abort immediately if XPCJSContext initialization fails.
     // Therefore the context must be non-null.
     MOZ_ASSERT(MaybeContext());
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1531,16 +1531,19 @@ pref("javascript.options.mem.gc_max_empt
 
 pref("javascript.options.showInConsole", false);
 
 pref("javascript.options.shared_memory", false);
 
 pref("javascript.options.throw_on_debuggee_would_run", false);
 pref("javascript.options.dump_stack_on_debuggee_would_run", false);
 
+// Spectre security vulnerability mitigations.
+pref("javascript.options.spectre.index_masking", false);
+
 // Streams API
 pref("javascript.options.streams", false);
 
 // advanced prefs
 pref("advanced.mailftp",                    false);
 pref("image.animation_mode",                "normal");
 
 // Same-origin policy for file URIs, "false" is traditional