mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
Bug 1438886 - Prevent speculative execution after returning from GC-capable C++ code. r=jandem
This commit is contained in:
parent
b7807456f1
commit
36b48bece7
@ -2007,8 +2007,8 @@ ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PR
|
||||
|
||||
for (unsigned int i = 0; i < prefsLen; i++) {
|
||||
const char* prefName = ContentPrefs::GetEarlyPref(i);
|
||||
MOZ_ASSERT_IF(i > 0,
|
||||
strcmp(prefName, ContentPrefs::GetEarlyPref(i - 1)) > 0);
|
||||
MOZ_ASSERT(i == 0 || strcmp(prefName, ContentPrefs::GetEarlyPref(i - 1)) > 0,
|
||||
"Content process preferences should be sorted alphabetically.");
|
||||
|
||||
if (!Preferences::MustSendToContentProcesses(prefName)) {
|
||||
continue;
|
||||
|
@ -129,6 +129,7 @@ const char* mozilla::dom::ContentPrefs::gEarlyPrefs[] = {
|
||||
"javascript.options.parallel_parsing",
|
||||
"javascript.options.shared_memory",
|
||||
"javascript.options.spectre.index_masking",
|
||||
"javascript.options.spectre.jit_to_C++_calls",
|
||||
"javascript.options.spectre.object_mitigations.barriers",
|
||||
"javascript.options.spectre.string_mitigations",
|
||||
"javascript.options.spectre.value_masking",
|
||||
|
@ -4305,6 +4305,14 @@ CodeGenerator::visitCallNative(LCallNative* call)
|
||||
// Load the outparam vp[0] into output register(s).
|
||||
masm.loadValue(Address(masm.getStackPointer(), NativeExitFrameLayout::offsetOfResult()), JSReturnOperand);
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (JitOptions.spectreJitToCxxCalls && !call->mir()->ignoresReturnValue() &&
|
||||
call->mir()->hasLiveDefUses())
|
||||
{
|
||||
masm.speculationBarrier();
|
||||
}
|
||||
|
||||
// The next instruction is removing the footer of the exit frame, so there
|
||||
// is no need for leaveFakeExitFrame.
|
||||
|
||||
@ -4443,6 +4451,11 @@ CodeGenerator::visitCallDOMNative(LCallDOMNative* call)
|
||||
JSReturnOperand);
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (JitOptions.spectreJitToCxxCalls && call->mir()->hasLiveDefUses())
|
||||
masm.speculationBarrier();
|
||||
|
||||
// The next instruction is removing the footer of the exit frame, so there
|
||||
// is no need for leaveFakeExitFrame.
|
||||
|
||||
@ -11993,6 +12006,12 @@ CodeGenerator::visitGetDOMProperty(LGetDOMProperty* ins)
|
||||
masm.loadValue(Address(masm.getStackPointer(), IonDOMExitFrameLayout::offsetOfResult()),
|
||||
JSReturnOperand);
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (JitOptions.spectreJitToCxxCalls && ins->mir()->hasLiveDefUses())
|
||||
masm.speculationBarrier();
|
||||
|
||||
masm.adjustStack(IonDOMExitFrameLayout::Size());
|
||||
|
||||
masm.bind(&haveValue);
|
||||
|
@ -238,6 +238,7 @@ DefaultJitOptions::DefaultJitOptions()
|
||||
SET_DEFAULT(spectreObjectMitigationsBarriers, true);
|
||||
SET_DEFAULT(spectreStringMitigations, true);
|
||||
SET_DEFAULT(spectreValueMasking, true);
|
||||
SET_DEFAULT(spectreJitToCxxCalls, true);
|
||||
|
||||
// Toggles whether unboxed plain objects can be created by the VM.
|
||||
SET_DEFAULT(disableUnboxedObjects, false);
|
||||
|
@ -102,6 +102,7 @@ struct DefaultJitOptions
|
||||
bool spectreObjectMitigationsBarriers;
|
||||
bool spectreStringMitigations;
|
||||
bool spectreValueMasking;
|
||||
bool spectreJitToCxxCalls;
|
||||
|
||||
// The options below affect the rest of the VM, and not just the JIT.
|
||||
bool disableUnboxedObjects;
|
||||
|
@ -3656,6 +3656,44 @@ MacroAssembler::emitPreBarrierFastPath(JSRuntime* rt, MIRType type, Register tem
|
||||
branchTestPtr(Assembler::NonZero, temp2, temp1, noBarrier);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Spectre Mitigations.
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(Register index, Register length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(length != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
move32(Imm32(0), output);
|
||||
cmp32Move32(Assembler::Below, index, length, index, output);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(Register index, const Address& length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(index != length.base);
|
||||
MOZ_ASSERT(length.base != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
move32(Imm32(0), output);
|
||||
cmp32Move32(Assembler::Below, index, length, index, output);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32PowerOfTwo(Register index, uint32_t length, Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(mozilla::IsPowerOfTwo(length));
|
||||
branch32(Assembler::AboveOrEqual, index, Imm32(length), failure);
|
||||
|
||||
// Note: it's fine to clobber the input register, as this is a no-op: it
|
||||
// only affects speculative execution.
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
and32(Imm32(length - 1), index);
|
||||
}
|
||||
|
||||
//}}} check_macroassembler_style
|
||||
|
||||
void
|
||||
@ -3707,41 +3745,6 @@ MacroAssembler::debugAssertObjHasFixedSlots(Register obj, Register scratch)
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(Register index, Register length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(length != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
move32(Imm32(0), output);
|
||||
cmp32Move32(Assembler::Below, index, length, index, output);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::spectreMaskIndex(Register index, const Address& length, Register output)
|
||||
{
|
||||
MOZ_ASSERT(JitOptions.spectreIndexMasking);
|
||||
MOZ_ASSERT(index != length.base);
|
||||
MOZ_ASSERT(length.base != output);
|
||||
MOZ_ASSERT(index != output);
|
||||
|
||||
move32(Imm32(0), output);
|
||||
cmp32Move32(Assembler::Below, index, length, index, output);
|
||||
}
|
||||
|
||||
void
|
||||
MacroAssembler::boundsCheck32PowerOfTwo(Register index, uint32_t length, Label* failure)
|
||||
{
|
||||
MOZ_ASSERT(mozilla::IsPowerOfTwo(length));
|
||||
branch32(Assembler::AboveOrEqual, index, Imm32(length), failure);
|
||||
|
||||
// Note: it's fine to clobber the input register, as this is a no-op: it
|
||||
// only affects speculative execution.
|
||||
if (JitOptions.spectreIndexMasking)
|
||||
and32(Imm32(length - 1), index);
|
||||
}
|
||||
|
||||
template <typename T, size_t N, typename P>
|
||||
static bool
|
||||
AddPendingReadBarrier(Vector<T*, N, P>& list, T* value)
|
||||
|
@ -1957,6 +1957,32 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
Register offsetTemp, Register maskTemp)
|
||||
DEFINED_ON(mips_shared);
|
||||
|
||||
// ========================================================================
|
||||
// Spectre Mitigations.
|
||||
//
|
||||
// Spectre attacks are side-channel attacks based on cache pollution or
|
||||
// slow-execution of some instructions. We have multiple spectre mitigations
|
||||
// possible:
|
||||
//
|
||||
// - Stop speculative executions, with memory barriers. Memory barriers
|
||||
// force all branches depending on loads to be resolved, and thus
|
||||
// resolve all miss-speculated paths.
|
||||
//
|
||||
// - Use conditional move instructions. Some CPUs have a branch predictor,
|
||||
// and not a flag predictor. In such cases, using a conditional move
|
||||
// instruction to zero some pointer/index is enough to add a
|
||||
// data-dependency which prevents any futher executions until the load is
|
||||
// resolved.
|
||||
|
||||
void spectreMaskIndex(Register index, Register length, Register output);
|
||||
void spectreMaskIndex(Register index, const Address& length, Register output);
|
||||
|
||||
// The length must be a power of two. Performs a bounds check and Spectre index
|
||||
// masking.
|
||||
void boundsCheck32PowerOfTwo(Register index, uint32_t length, Label* failure);
|
||||
|
||||
void speculationBarrier() PER_SHARED_ARCH;
|
||||
|
||||
//}}} check_macroassembler_decl_style
|
||||
public:
|
||||
|
||||
@ -2141,13 +2167,6 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||
store32(Imm32(key.constant()), dest);
|
||||
}
|
||||
|
||||
void spectreMaskIndex(Register index, Register length, Register output);
|
||||
void spectreMaskIndex(Register index, const Address& length, Register output);
|
||||
|
||||
// The length must be a power of two. Performs a bounds check and Spectre index
|
||||
// masking.
|
||||
void boundsCheck32PowerOfTwo(Register index, uint32_t length, Label* failure);
|
||||
|
||||
template <typename T>
|
||||
void guardedCallPreBarrier(const T& address, MIRType type) {
|
||||
Label done;
|
||||
|
@ -149,6 +149,12 @@ struct VMFunction
|
||||
return returnType;
|
||||
}
|
||||
|
||||
// Whether this function returns anything more than a boolean flag for
|
||||
// failures.
|
||||
bool returnsData() const {
|
||||
return returnType == Type_Pointer || outParam != Type_Void;
|
||||
}
|
||||
|
||||
ArgProperties argProperties(uint32_t explicitArg) const {
|
||||
return ArgProperties((argumentProperties >> (2 * explicitArg)) & 3);
|
||||
}
|
||||
|
@ -2163,6 +2163,16 @@ Assembler::as_isb_trap()
|
||||
return writeInst(0xee070f94);
|
||||
}
|
||||
|
||||
BufferOffset
|
||||
Assembler::as_csdb()
|
||||
{
|
||||
// NOP (see as_nop) on architectures where this instruction is not defined.
|
||||
//
|
||||
// https://developer.arm.com/-/media/developer/pdf/Cache_Speculation_Side-channels_22Feb18.pdf
|
||||
// CSDB A32: 1110_0011_0010_0000_1111_0000_0001_0100
|
||||
return writeInst(0xe320f000 | 0x14);
|
||||
}
|
||||
|
||||
// Control flow stuff:
|
||||
|
||||
// bx can *only* branch to a register, never to an immediate.
|
||||
|
@ -1606,6 +1606,9 @@ class Assembler : public AssemblerShared
|
||||
BufferOffset as_dmb_trap();
|
||||
BufferOffset as_isb_trap();
|
||||
|
||||
// Speculation barrier
|
||||
BufferOffset as_csdb();
|
||||
|
||||
// Control flow stuff:
|
||||
|
||||
// bx can *only* branch to a register never to an immediate.
|
||||
|
@ -5785,6 +5785,17 @@ MacroAssembler::convertUInt64ToDouble(Register64 src, FloatRegister dest, Regist
|
||||
addDouble(scratchDouble, dest);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Spectre Mitigations.
|
||||
|
||||
void
|
||||
MacroAssembler::speculationBarrier()
|
||||
{
|
||||
// Spectre mitigation recommended by ARM for cases where csel/cmov cannot be
|
||||
// used.
|
||||
as_csdb();
|
||||
}
|
||||
|
||||
//}}} check_macroassembler_style
|
||||
|
||||
void
|
||||
|
@ -282,6 +282,9 @@ class SimInstruction {
|
||||
// Test for a nop instruction, which falls under type 1.
|
||||
inline bool isNopType1() const { return bits(24, 0) == 0x0120F000; }
|
||||
|
||||
// Test for a nop instruction, which falls under type 1.
|
||||
inline bool isCsdbType1() const { return bits(24, 0) == 0x0120F014; }
|
||||
|
||||
// Test for a stop instruction.
|
||||
inline bool isStop() const {
|
||||
return typeValue() == 7 && bit(24) == 1 && svcValue() >= kStopCode;
|
||||
@ -3387,6 +3390,8 @@ Simulator::decodeType01(SimInstruction* instr)
|
||||
}
|
||||
} else if ((type == 1) && instr->isNopType1()) {
|
||||
// NOP.
|
||||
} else if ((type == 1) && instr->isCsdbType1()) {
|
||||
// Speculation barrier. (No-op for the simulator)
|
||||
} else {
|
||||
int rd = instr->rdValue();
|
||||
int rn = instr->rnValue();
|
||||
|
@ -878,6 +878,12 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct
|
||||
MOZ_ASSERT(f.outParam == Type_Void);
|
||||
break;
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (f.returnsData() && JitOptions.spectreJitToCxxCalls)
|
||||
masm.speculationBarrier();
|
||||
|
||||
masm.leaveExitFrame();
|
||||
masm.retn(Imm32(sizeof(ExitFrameLayout) +
|
||||
f.explicitStackSlots() * sizeof(void*) +
|
||||
|
@ -1862,6 +1862,16 @@ MacroAssembler::atomicEffectOpJS(Scalar::Type arrayType, const Synchronization&
|
||||
atomicEffectOp(arrayType, sync, op, value, mem, temp);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Spectre Mitigations.
|
||||
|
||||
void
|
||||
MacroAssembler::speculationBarrier()
|
||||
{
|
||||
// Conditional speculation barrier.
|
||||
csdb();
|
||||
}
|
||||
|
||||
//}}} check_macroassembler_style
|
||||
|
||||
} // namespace jit
|
||||
|
@ -702,6 +702,11 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct
|
||||
break;
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (f.returnsData() && JitOptions.spectreJitToCxxCalls)
|
||||
masm.speculationBarrier();
|
||||
|
||||
masm.leaveExitFrame();
|
||||
masm.retn(Imm32(sizeof(ExitFrameLayout) +
|
||||
f.explicitStackSlots() * sizeof(void*) +
|
||||
|
@ -1818,6 +1818,13 @@ class Assembler : public MozBaseAssembler {
|
||||
}
|
||||
static void nop(Instruction* at);
|
||||
|
||||
// Alias for system instructions.
|
||||
// Conditional speculation barrier.
|
||||
BufferOffset csdb() {
|
||||
return hint(CSDB);
|
||||
}
|
||||
static void csdb(Instruction* at);
|
||||
|
||||
// FP and NEON instructions.
|
||||
// Move double precision immediate to FP register.
|
||||
void fmov(const VRegister& vd, double imm);
|
||||
|
@ -321,7 +321,10 @@ enum SystemHint {
|
||||
WFE = 2,
|
||||
WFI = 3,
|
||||
SEV = 4,
|
||||
SEVL = 5
|
||||
SEVL = 5,
|
||||
// No-op on architectures where this instruction is not defined.
|
||||
// https://developer.arm.com/-/media/developer/pdf/Cache_Speculation_Side-channels_22Feb18.pdf
|
||||
CSDB = 0x14
|
||||
};
|
||||
|
||||
enum BarrierDomain {
|
||||
|
@ -228,7 +228,7 @@ void Decoder::DecodeBranchSystemException(const Instruction* instr) {
|
||||
(instr->Mask(0x003CE000) == 0x00042000) ||
|
||||
(instr->Mask(0x003FFFC0) == 0x000320C0) ||
|
||||
(instr->Mask(0x003FF100) == 0x00032100) ||
|
||||
(instr->Mask(0x003FF200) == 0x00032200) ||
|
||||
// (instr->Mask(0x003FF200) == 0x00032200) || // match CSDB
|
||||
(instr->Mask(0x003FF400) == 0x00032400) ||
|
||||
(instr->Mask(0x003FF800) == 0x00032800) ||
|
||||
(instr->Mask(0x0038F000) == 0x00005000) ||
|
||||
|
@ -1321,6 +1321,11 @@ void Disassembler::VisitSystem(const Instruction* instr) {
|
||||
form = NULL;
|
||||
break;
|
||||
}
|
||||
case CSDB: {
|
||||
mnemonic = "csdb";
|
||||
form = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
|
||||
switch (instr->Mask(MemBarrierMask)) {
|
||||
|
@ -309,6 +309,7 @@ class Instruction {
|
||||
bool IsCBNZ() const;
|
||||
bool IsLDR() const;
|
||||
bool IsNOP() const;
|
||||
bool IsCSDB() const;
|
||||
bool IsADR() const;
|
||||
bool IsADRP() const;
|
||||
bool IsMovz() const;
|
||||
|
@ -1123,6 +1123,10 @@ class MacroAssembler : public js::jit::Assembler {
|
||||
SingleEmissionCheckScope guard(this);
|
||||
nop();
|
||||
}
|
||||
void Csdb() {
|
||||
SingleEmissionCheckScope guard(this);
|
||||
csdb();
|
||||
}
|
||||
void Rbit(const Register& rd, const Register& rn) {
|
||||
VIXL_ASSERT(!rd.IsZero());
|
||||
VIXL_ASSERT(!rn.IsZero());
|
||||
|
@ -409,6 +409,11 @@ void Assembler::nop(Instruction* at) {
|
||||
}
|
||||
|
||||
|
||||
void Assembler::csdb(Instruction* at) {
|
||||
hint(at, CSDB);
|
||||
}
|
||||
|
||||
|
||||
BufferOffset Assembler::Logical(const Register& rd, const Register& rn,
|
||||
const Operand operand, LogicalOp op)
|
||||
{
|
||||
|
@ -85,6 +85,11 @@ bool Instruction::IsNOP() const {
|
||||
}
|
||||
|
||||
|
||||
bool Instruction::IsCSDB() const {
|
||||
return Mask(SystemHintMask) == HINT && ImmHint() == CSDB;
|
||||
}
|
||||
|
||||
|
||||
bool Instruction::IsADR() const {
|
||||
return Mask(PCRelAddressingMask) == ADR;
|
||||
}
|
||||
|
@ -2326,6 +2326,7 @@ void Simulator::VisitSystem(const Instruction* instr) {
|
||||
VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
|
||||
switch (instr->ImmHint()) {
|
||||
case NOP: break;
|
||||
case CSDB: break;
|
||||
default: VIXL_UNIMPLEMENTED();
|
||||
}
|
||||
} else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
|
||||
|
@ -766,6 +766,12 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct
|
||||
MOZ_ASSERT(f.outParam == Type_Void);
|
||||
break;
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (f.returnsData() && JitOptions.spectreJitToCxxCalls)
|
||||
masm.speculationBarrier();
|
||||
|
||||
masm.leaveExitFrame();
|
||||
masm.retn(Imm32(sizeof(ExitFrameLayout) +
|
||||
f.explicitStackSlots() * sizeof(void*) +
|
||||
|
@ -3743,9 +3743,13 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off
|
||||
m_formatter.immediate16u(imm);
|
||||
}
|
||||
|
||||
void lfence() {
|
||||
spew("lfence");
|
||||
m_formatter.twoByteOp(OP_FENCE, (RegisterID)0, 0b101);
|
||||
}
|
||||
void mfence() {
|
||||
spew("mfence");
|
||||
m_formatter.twoByteOp(OP_FENCE, (RegisterID)0, 6);
|
||||
m_formatter.twoByteOp(OP_FENCE, (RegisterID)0, 0b110);
|
||||
}
|
||||
|
||||
// Assembler admin methods:
|
||||
|
@ -1418,4 +1418,16 @@ MacroAssembler::atomicFetchOpJS(Scalar::Type arrayType, const Synchronization& s
|
||||
AtomicFetchOpJS(*this, arrayType, sync, op, value, mem, temp1, temp2, output);
|
||||
}
|
||||
|
||||
// ========================================================================
|
||||
// Spectre Mitigations.
|
||||
|
||||
void
|
||||
MacroAssembler::speculationBarrier()
|
||||
{
|
||||
// Spectre mitigation recommended by Intel and AMD suggest to use lfence as
|
||||
// a way to force all speculative execution of instructions to end.
|
||||
MOZ_ASSERT(HasSSE2());
|
||||
masm.lfence();
|
||||
}
|
||||
|
||||
//}}} check_macroassembler_style
|
||||
|
@ -782,6 +782,12 @@ JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm, const VMFunct
|
||||
MOZ_ASSERT(f.outParam == Type_Void);
|
||||
break;
|
||||
}
|
||||
|
||||
// Until C++ code is instrumented against Spectre, prevent speculative
|
||||
// execution from returning any private data.
|
||||
if (f.returnsData() && JitOptions.spectreJitToCxxCalls)
|
||||
masm.speculationBarrier();
|
||||
|
||||
masm.leaveExitFrame();
|
||||
masm.retn(Imm32(sizeof(ExitFrameLayout) +
|
||||
f.explicitStackSlots() * sizeof(void*) +
|
||||
|
@ -7287,6 +7287,9 @@ JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t v
|
||||
case JSJITCOMPILER_SPECTRE_VALUE_MASKING:
|
||||
jit::JitOptions.spectreValueMasking = !!value;
|
||||
break;
|
||||
case JSJITCOMPILER_SPECTRE_JIT_TO_CXX_CALLS:
|
||||
jit::JitOptions.spectreJitToCxxCalls = !!value;
|
||||
break;
|
||||
case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE:
|
||||
jit::JitOptions.asmJSAtomicsEnable = !!value;
|
||||
break;
|
||||
|
@ -5894,6 +5894,7 @@ JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled);
|
||||
Register(SPECTRE_OBJECT_MITIGATIONS_BARRIERS, "spectre.object-mitigations.barriers") \
|
||||
Register(SPECTRE_STRING_MITIGATIONS, "spectre.string-mitigations") \
|
||||
Register(SPECTRE_VALUE_MASKING, "spectre.value-masking") \
|
||||
Register(SPECTRE_JIT_TO_CXX_CALLS, "spectre.jit-to-C++-calls") \
|
||||
Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \
|
||||
Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets") \
|
||||
Register(WASM_DELAY_TIER2, "wasm.delay-tier2")
|
||||
|
@ -8601,11 +8601,13 @@ SetContextOptions(JSContext* cx, const OptionParser& op)
|
||||
jit::JitOptions.spectreObjectMitigationsBarriers = true;
|
||||
jit::JitOptions.spectreStringMitigations = true;
|
||||
jit::JitOptions.spectreValueMasking = true;
|
||||
jit::JitOptions.spectreJitToCxxCalls = true;
|
||||
} else if (strcmp(str, "off") == 0) {
|
||||
jit::JitOptions.spectreIndexMasking = false;
|
||||
jit::JitOptions.spectreObjectMitigationsBarriers = false;
|
||||
jit::JitOptions.spectreStringMitigations = false;
|
||||
jit::JitOptions.spectreValueMasking = false;
|
||||
jit::JitOptions.spectreJitToCxxCalls = false;
|
||||
} else {
|
||||
return OptionFailure("spectre-mitigations", str);
|
||||
}
|
||||
|
@ -813,6 +813,7 @@ ReloadPrefsCallback(const char* pref, void* data)
|
||||
bool spectreStringMitigations =
|
||||
Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.string_mitigations");
|
||||
bool spectreValueMasking = Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.value_masking");
|
||||
bool spectreJitToCxxCalls = Preferences::GetBool(JS_OPTIONS_DOT_STR "spectre.jit_to_C++_calls");
|
||||
|
||||
sSharedMemoryEnabled = Preferences::GetBool(JS_OPTIONS_DOT_STR "shared_memory");
|
||||
|
||||
@ -880,6 +881,8 @@ ReloadPrefsCallback(const char* pref, void* data)
|
||||
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_STRING_MITIGATIONS,
|
||||
spectreStringMitigations);
|
||||
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_VALUE_MASKING, spectreValueMasking);
|
||||
JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_SPECTRE_JIT_TO_CXX_CALLS,
|
||||
spectreJitToCxxCalls);
|
||||
}
|
||||
|
||||
XPCJSContext::~XPCJSContext()
|
||||
|
@ -1576,6 +1576,7 @@ pref("javascript.options.spectre.index_masking", true);
|
||||
pref("javascript.options.spectre.object_mitigations.barriers", true);
|
||||
pref("javascript.options.spectre.string_mitigations", true);
|
||||
pref("javascript.options.spectre.value_masking", true);
|
||||
pref("javascript.options.spectre.jit_to_C++_calls", true);
|
||||
|
||||
// Streams API
|
||||
pref("javascript.options.streams", false);
|
||||
|
Loading…
Reference in New Issue
Block a user