From 35a6c3e5b3e8572dbe188d5bd70270e5cc9b5010 Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Thu, 5 Apr 2018 15:15:13 +0000 Subject: [PATCH] Bug 1437510 - ARM: Zero the payload if the Value tag does not match the expected tag. r=jandem --- js/src/jit/arm/CodeGenerator-arm.cpp | 7 ++++ js/src/jit/arm/MacroAssembler-arm.cpp | 58 ++++++++++++++++++++++----- js/src/jit/arm/MacroAssembler-arm.h | 3 ++ 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/js/src/jit/arm/CodeGenerator-arm.cpp b/js/src/jit/arm/CodeGenerator-arm.cpp index 23f8f26d89e3..e0496f9744be 100644 --- a/js/src/jit/arm/CodeGenerator-arm.cpp +++ b/js/src/jit/arm/CodeGenerator-arm.cpp @@ -1430,6 +1430,8 @@ CodeGenerator::visitUnbox(LUnbox* unbox) // inputs. MUnbox* mir = unbox->mir(); Register type = ToRegister(unbox->type()); + Register payload = ToRegister(unbox->payload()); + Register output = ToRegister(unbox->output()); mozilla::Maybe scratch; scratch.emplace(masm); @@ -1448,6 +1450,11 @@ CodeGenerator::visitUnbox(LUnbox* unbox) masm.bind(&ok); #endif } + + // Note: If spectreValueMasking is disabled, then this instruction will + // default to a no-op as long as the lowering allocate the same register for + // the output and the payload. + masm.unboxNonDouble(ValueOperand(type, payload), output, ValueTypeFromMIRType(mir->type())); } void diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index f1df87ae4a0f..a3985f2c24d1 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -3000,26 +3000,62 @@ MacroAssemblerARMCompat::testGCThing(Condition cond, const BaseIndex& address) // Unboxing code. void -MacroAssemblerARMCompat::unboxNonDouble(const ValueOperand& operand, Register dest, JSValueType) +MacroAssemblerARMCompat::unboxNonDouble(const ValueOperand& operand, Register dest, JSValueType type) { - if (operand.payloadReg() != dest) - ma_mov(operand.payloadReg(), dest); + auto movPayloadToDest = [&]() { + if (operand.payloadReg() != dest) + ma_mov(operand.payloadReg(), dest, LeaveCC); + }; + if (!JitOptions.spectreValueMasking) { + movPayloadToDest(); + return; + } + + // Spectre mitigation: We zero the payload if the tag does not match the + // expected type and if this is a pointer type. + if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) { + movPayloadToDest(); + return; + } + + // We zero the destination register and move the payload into it if + // the tag corresponds to the given type. + ma_cmp(operand.typeReg(), ImmType(type)); + movPayloadToDest(); + ma_mov(Imm32(0), dest, NotEqual); } void -MacroAssemblerARMCompat::unboxNonDouble(const Address& src, Register dest, JSValueType) +MacroAssemblerARMCompat::unboxNonDouble(const Address& src, Register dest, JSValueType type) { ScratchRegisterScope scratch(asMasm()); - ma_ldr(ToPayload(src), dest, scratch); + if (!JitOptions.spectreValueMasking) { + ma_ldr(ToPayload(src), dest, scratch); + return; + } + + // Spectre mitigation: We zero the payload if the tag does not match the + // expected type and if this is a pointer type. + if (type == JSVAL_TYPE_INT32 || type == JSVAL_TYPE_BOOLEAN) { + ma_ldr(ToPayload(src), dest, scratch); + return; + } + + // We zero the destination register and move the payload into it if + // the tag corresponds to the given type. + ma_ldr(ToType(src), scratch, scratch); + ma_cmp(scratch, ImmType(type)); + ma_ldr(ToPayload(src), dest, scratch, Offset, Equal); + ma_mov(Imm32(0), dest, NotEqual); } void -MacroAssemblerARMCompat::unboxNonDouble(const BaseIndex& src, Register dest, JSValueType) +MacroAssemblerARMCompat::unboxNonDouble(const BaseIndex& src, Register dest, JSValueType type) { - ScratchRegisterScope scratch(asMasm()); SecondScratchRegisterScope scratch2(asMasm()); - ma_alu(src.base, lsl(src.index, src.scale), scratch, OpAdd); - ma_ldr(Address(scratch, src.offset), dest, scratch2); + ma_alu(src.base, lsl(src.index, src.scale), scratch2, OpAdd); + Address value(scratch2, src.offset); + unboxNonDouble(value, dest, type); } void @@ -3048,8 +3084,8 @@ MacroAssemblerARMCompat::unboxValue(const ValueOperand& src, AnyRegister dest, J bind(¬Int32); unboxDouble(src, dest.fpu()); bind(&end); - } else if (src.payloadReg() != dest.gpr()) { - as_mov(dest.gpr(), O2Reg(src.payloadReg())); + } else { + unboxNonDouble(src, dest.gpr(), type); } } diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 47ad813740a0..1124faa9a29b 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -829,12 +829,15 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM // and returns that. Register extractObject(const Address& address, Register scratch); Register extractObject(const ValueOperand& value, Register scratch) { + unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_OBJECT); return value.payloadReg(); } Register extractString(const ValueOperand& value, Register scratch) { + unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_STRING); return value.payloadReg(); } Register extractSymbol(const ValueOperand& value, Register scratch) { + unboxNonDouble(value, value.payloadReg(), JSVAL_TYPE_SYMBOL); return value.payloadReg(); } Register extractInt32(const ValueOperand& value, Register scratch) {