Skip to content

Commit e664e18

Browse files
PenguinwizzardMSLaguana
authored andcommitted
Add masking of stores for protection against Spectre.
1 parent eb4b00b commit e664e18

File tree

9 files changed

+279
-61
lines changed

9 files changed

+279
-61
lines changed

lib/Backend/Lower.cpp

Lines changed: 204 additions & 49 deletions
Large diffs are not rendered by default.

lib/Backend/Lower.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ class Lowerer
649649
IR::Instr * LowerSlotArrayCheck(IR::Instr * instr);
650650
void InsertSlotArrayCheck(IR::Instr * instr, StackSym * dstSym, uint32 slotId);
651651
void InsertFrameDisplayCheck(IR::Instr * instr, StackSym * dstSym, FrameDisplayCheckRecord * record);
652-
static void InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr);
652+
static void InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr, bool isForStore);
653653

654654
IR::RegOpnd * LoadIndexFromLikelyFloat(IR::RegOpnd *indexOpnd, const bool skipNegativeCheck, IR::LabelInstr *const notTaggedIntLabel, IR::LabelInstr *const negativeLabel, IR::Instr *const insertBeforeInstr);
655655

lib/Backend/LowerMDShared.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7149,7 +7149,7 @@ bool LowererMD::GenerateObjectTest(IR::Opnd * opndSrc, IR::Instr * insertInstr,
71497149
// JNE $labelHelper
71507150
IR::BranchInstr* branchInstr = IR::BranchInstr::New(Js::OpCode::JNE, labelTarget, this->m_func);
71517151
insertInstr->InsertBefore(branchInstr);
7152-
InsertObjectPoison(opndSrc, branchInstr, insertInstr);
7152+
InsertObjectPoison(opndSrc, branchInstr, insertInstr, false);
71537153
}
71547154
return true;
71557155
}
@@ -9464,9 +9464,9 @@ LowererMD::LowerTypeof(IR::Instr * typeOfInstr)
94649464
}
94659465

94669466
void
9467-
LowererMD::InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr)
9467+
LowererMD::InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr, bool isForStore)
94689468
{
9469-
if (CONFIG_FLAG_RELEASE(PoisonObjects))
9469+
if ((isForStore && CONFIG_FLAG_RELEASE(PoisonObjectsForStores)) || (!isForStore && CONFIG_FLAG_RELEASE(PoisonObjectsForLoads)))
94709470
{
94719471
Js::OpCode opcode;
94729472
if (branchInstr->m_opcode == Js::OpCode::JNE)
@@ -9475,7 +9475,7 @@ LowererMD::InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchIns
94759475
}
94769476
else
94779477
{
9478-
AssertOrFailFast(branchInstr->m_opcode == Js::OpCode::JEQ);
9478+
AssertOrFailFastMsg(branchInstr->m_opcode == Js::OpCode::JEQ, "Unexpected branch type in InsertObjectPoison preceeding instruction");
94799479
opcode = Js::OpCode::CMOVE;
94809480
}
94819481
AssertOrFailFast(branchInstr->m_prev->m_opcode == Js::OpCode::CMP || branchInstr->m_prev->m_opcode == Js::OpCode::TEST);

lib/Backend/LowerMDShared.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ class LowererMD
248248
void GenerateIsJsObjectTest(IR::RegOpnd* instanceReg, IR::Instr* insertInstr, IR::LabelInstr* labelHelper);
249249
void LowerTypeof(IR::Instr * typeOfInstr);
250250

251-
static void InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr);
251+
static void InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr, bool isForStore);
252252
public:
253253
//
254254
// These methods are simply forwarded to lowererMDArch

lib/Backend/arm64/LowerMD.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7954,9 +7954,9 @@ LowererMD::LowerTypeof(IR::Instr* typeOfInstr)
79547954
}
79557955

79567956
void
7957-
LowererMD::InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr)
7957+
LowererMD::InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr, bool isForStore)
79587958
{
7959-
if (CONFIG_FLAG_RELEASE(PoisonObjects))
7959+
if ((isForStore && CONFIG_FLAG_RELEASE(PoisonObjectsForStores)) || (!isForStore && CONFIG_FLAG_RELEASE(PoisonObjectsForLoads)))
79607960
{
79617961
Js::OpCode opcode;
79627962
if (branchInstr->m_opcode == Js::OpCode::BNE)
@@ -7965,7 +7965,7 @@ LowererMD::InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchIns
79657965
}
79667966
else
79677967
{
7968-
AssertOrFailFast(branchInstr->m_opcode == Js::OpCode::BEQ);
7968+
AssertOrFailFastMsg(branchInstr->m_opcode == Js::OpCode::BEQ, "Unexpected branch type in InsertObjectPoison preceeding instruction");
79697969
opcode = Js::OpCode::CSELNE;
79707970
}
79717971
AssertOrFailFast(branchInstr->m_prev->m_opcode == Js::OpCode::SUBS || branchInstr->m_prev->m_opcode == Js::OpCode::ANDS);

lib/Backend/arm64/LowerMD.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,8 @@ class LowererMD
270270

271271
void GenerateMemInit(IR::RegOpnd * opnd, int32 offset, size_t value, IR::Instr * insertBeforeInstr, bool isZeroed = false);
272272

273-
static void InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr);
273+
static void InsertObjectPoison(IR::Opnd* poisonedOpnd, IR::BranchInstr* branchInstr, IR::Instr* insertInstr, bool isForStore);
274+
274275
private:
275276
static IR::Instr * ChangeToAssign(IR::Instr * instr, IRType destType);
276277
void GenerateFlagInlineCacheCheckForGetterSetter(

lib/Common/ConfigFlagsList.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,13 @@ PHASE(All)
495495
#define DEFAULT_CONFIG_PoisonFloatArrayLoad (true)
496496
#define DEFAULT_CONFIG_PoisonTypedArrayLoad (true)
497497
#define DEFAULT_CONFIG_PoisonStringLoad (true)
498-
#define DEFAULT_CONFIG_PoisonObjects (true)
498+
#define DEFAULT_CONFIG_PoisonObjectsForLoads (true)
499+
500+
#define DEFAULT_CONFIG_PoisonVarArrayStore (true)
501+
#define DEFAULT_CONFIG_PoisonIntArrayStore (true)
502+
#define DEFAULT_CONFIG_PoisonFloatArrayStore (true)
503+
#define DEFAULT_CONFIG_PoisonTypedArrayStore (true)
504+
#define DEFAULT_CONFIG_PoisonObjectsForStores (true)
499505

500506
#ifdef RECYCLER_PAGE_HEAP
501507
#define DEFAULT_CONFIG_PageHeap ((Js::Number) PageHeapMode::PageHeapModeOff)
@@ -1244,7 +1250,13 @@ FLAGPR(Boolean, MitigateSpectre, PoisonIntArrayLoad, "Poison loads from Int arra
12441250
FLAGPR(Boolean, MitigateSpectre, PoisonFloatArrayLoad, "Poison loads from Float arrays", DEFAULT_CONFIG_PoisonFloatArrayLoad)
12451251
FLAGPR(Boolean, MitigateSpectre, PoisonTypedArrayLoad, "Poison loads from TypedArrays", DEFAULT_CONFIG_PoisonTypedArrayLoad)
12461252
FLAGPR(Boolean, MitigateSpectre, PoisonStringLoad, "Poison indexed loads from strings", DEFAULT_CONFIG_PoisonStringLoad)
1247-
FLAGPR(Boolean, MitigateSpectre, PoisonObjects, "Poison objects after type checks", DEFAULT_CONFIG_PoisonObjects)
1253+
FLAGPR(Boolean, MitigateSpectre, PoisonObjectsForLoads, "Poison objects after type checks", DEFAULT_CONFIG_PoisonObjectsForLoads)
1254+
1255+
FLAGPR(Boolean, MitigateSpectre, PoisonVarArrayStore, "Poison stores from Var arrays", DEFAULT_CONFIG_PoisonVarArrayStore)
1256+
FLAGPR(Boolean, MitigateSpectre, PoisonIntArrayStore, "Poison stores from Int arrays", DEFAULT_CONFIG_PoisonIntArrayStore)
1257+
FLAGPR(Boolean, MitigateSpectre, PoisonFloatArrayStore, "Poison stores from Float arrays", DEFAULT_CONFIG_PoisonFloatArrayStore)
1258+
FLAGPR(Boolean, MitigateSpectre, PoisonTypedArrayStore, "Poison stores from TypedArrays", DEFAULT_CONFIG_PoisonTypedArrayStore)
1259+
FLAGPR(Boolean, MitigateSpectre, PoisonObjectsForStores, "Poison objects after type checks", DEFAULT_CONFIG_PoisonObjectsForStores)
12481260

12491261
FLAGNR(Number, MinInterpretCount , "Minimum number of times a function must be interpreted", 0)
12501262
FLAGNR(Number, MinSimpleJitRunCount , "Minimum number of times a function must be run in simple jit", 0)

test/typedarray/Uint8ClampedArray2.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
var log = Array(1000000);
7+
var i = 0;
8+
9+
function test() {
10+
var cqjmyu;
11+
for (var wetavm = 0; wetavm < 1000; ++wetavm) {
12+
cqjmyu = new Uint16Array([1, 1, 1, 1, 1, 1, 1, 1, 1]);
13+
cqjmyu_0 = new Uint8ClampedArray(cqjmyu);
14+
cqjmyu_0[8] = "5";
15+
log[i++] = cqjmyu_0[0];
16+
}
17+
return cqjmyu[0];
18+
}
19+
for(var j =0;j<100;j++) test();
20+
test();
21+
test();
22+
test();
23+
test();
24+
test();
25+
test();
26+
test();
27+
test();
28+
test();
29+
test();
30+
test();
31+
32+
var failed = false;
33+
for(var k = 0; k < i; k++) {
34+
if(log[k] != 1) {
35+
WScript.Echo("failed at " + k);
36+
failed = true;
37+
break;
38+
}
39+
}
40+
if(!failed)
41+
{
42+
WScript.Echo("PASSED");
43+
}

test/typedarray/rlexe.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,13 @@ Below test fails with difference in space. Investigate the cause and re-enable t
299299
<tags>typedarray</tags>
300300
</default>
301301
</test>
302+
<test>
303+
<default>
304+
<files>Uint8ClampedArray2.js</files>
305+
<tags>typedarray</tags>
306+
<compile-flags>-minInterpretCount:1 -maxInterpretCount:1 -off:simpleJit</compile-flags>
307+
</default>
308+
</test>
302309
<test>
303310
<default>
304311
<files>setDifferentTypes.js</files>

0 commit comments

Comments
 (0)