Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (247100 => 247101)
--- trunk/Source/_javascript_Core/ChangeLog 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-07-03 20:25:14 UTC (rev 247101)
@@ -1,3 +1,63 @@
+2019-07-03 Keith Miller <[email protected]>
+
+ PACCage should first cage leaving PAC bits intact then authenticate
+ https://bugs.webkit.org/show_bug.cgi?id=199372
+
+ Reviewed by Saam Barati.
+
+ This ordering prevents someone from taking a signed pointer from
+ outside the gigacage and using it in a struct that expects a caged
+ pointer. Previously, the PACCaging just double checked that the PAC
+ bits were valid for the original pointer.
+
+
+ +---------------------------+
+ | | | |
+ | "PAC" | "base" | "offset" +----+
+ | | | | |
+ +---------------------------+ | Caging
+ | |
+ | |
+ | v
+ | +---------------------------+
+ | | | | |
+ | Bit Merge | 00000 | base | "offset" |
+ | | | | |
+ | +---------------------------+
+ | |
+ | |
+ v | Bit Merge
+ +---------------------------+ |
+ | | | | |
+ | "PAC" | base | "offset" +<--------+
+ | | | |
+ +---------------------------+
+ |
+ |
+ | Authenticate
+ |
+ v
+ +---------------------------+
+ | | | |
+ | Auth | base | "offset" |
+ | | | |
+ +---------------------------+
+
+ The above ascii art graph shows how the PACCage system works. The
+ key take away is that even if someone passes in a valid, signed
+ pointer outside the cage it will still fail to authenticate as the
+ "base" bits will change before authentication.
+
+
+ * assembler/MacroAssemblerARM64E.h:
+ * assembler/testmasm.cpp:
+ (JSC::testCagePreservesPACFailureBit):
+ * ftl/FTLLowerDFGToB3.cpp:
+ (JSC::FTL::DFG::LowerDFGToB3::caged):
+ * jit/AssemblyHelpers.h:
+ (JSC::AssemblyHelpers::cageConditionally):
+ * llint/LowLevelInterpreter64.asm:
+
2019-07-03 Paulo Matos <[email protected]>
Refactoring of architectural Register Information
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64E.h (247100 => 247101)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64E.h 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64E.h 2019-07-03 20:25:14 UTC (rev 247101)
@@ -40,6 +40,7 @@
class MacroAssemblerARM64E : public MacroAssemblerARM64 {
public:
static constexpr unsigned numberOfPACBits = 25;
+ static constexpr uintptr_t nonPACBitsMask = (1ull << (64 - numberOfPACBits)) - 1;
ALWAYS_INLINE void tagReturnAddress()
{
Modified: trunk/Source/_javascript_Core/assembler/testmasm.cpp (247100 => 247101)
--- trunk/Source/_javascript_Core/assembler/testmasm.cpp 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/_javascript_Core/assembler/testmasm.cpp 2019-07-03 20:25:14 UTC (rev 247101)
@@ -1015,6 +1015,8 @@
static void testCagePreservesPACFailureBit()
{
+#if GIGACAGE_ENABLED
+ ASSERT(!Gigacage::isDisablingPrimitiveGigacageDisabled());
auto cage = compile([] (CCallHelpers& jit) {
jit.emitFunctionPrologue();
jit.cageConditionally(Gigacage::Primitive, GPRInfo::argumentGPR0, GPRInfo::argumentGPR1, GPRInfo::argumentGPR2);
@@ -1025,10 +1027,15 @@
void* ptr = Gigacage::tryMalloc(Gigacage::Primitive, 1);
void* taggedPtr = tagArrayPtr(ptr, 1);
- dataLogLn("starting test");
+ ASSERT(hasOneBitSet(Gigacage::size(Gigacage::Primitive) << 2));
+ void* notCagedPtr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ptr) + (Gigacage::size(Gigacage::Primitive) << 2));
+ CHECK_NOT_EQ(Gigacage::caged(Gigacage::Primitive, notCagedPtr), notCagedPtr);
+ void* taggedNotCagedPtr = tagArrayPtr(notCagedPtr, 1);
+
if (isARM64E()) {
// FIXME: This won't work if authentication failures trap but I don't know how to test for that right now.
CHECK_NOT_EQ(invoke<void*>(cage, taggedPtr, 2), ptr);
+ CHECK_EQ(invoke<void*>(cage, taggedNotCagedPtr, 1), untagArrayPtr(taggedPtr, 2));
} else
CHECK_EQ(invoke<void*>(cage, taggedPtr, 2), ptr);
@@ -1042,16 +1049,17 @@
jit.ret();
});
+ CHECK_EQ(invoke<void*>(cageWithoutAuthentication, taggedPtr), taggedPtr);
if (isARM64E()) {
// FIXME: This won't work if authentication failures trap but I don't know how to test for that right now.
- CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, untagArrayPtr(taggedPtr, 2)), ptr);
- } else
- CHECK_EQ(invoke<void*>(cageWithoutAuthentication, untagArrayPtr(taggedPtr, 2)), ptr);
+ CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), taggedNotCagedPtr);
+ CHECK_NOT_EQ(untagArrayPtr(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), 1), notCagedPtr);
+ CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), taggedPtr);
+ CHECK_NOT_EQ(untagArrayPtr(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), 1), ptr);
+ }
- CHECK_EQ(untagArrayPtr(taggedPtr, 1), ptr);
- CHECK_EQ(invoke<void*>(cageWithoutAuthentication, untagArrayPtr(taggedPtr, 1)), ptr);
-
Gigacage::free(Gigacage::Primitive, ptr);
+#endif
}
#define RUN(test) do { \
Modified: trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp (247100 => 247101)
--- trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/_javascript_Core/ftl/FTLLowerDFGToB3.cpp 2019-07-03 20:25:14 UTC (rev 247101)
@@ -14177,18 +14177,7 @@
LValue caged(Gigacage::Kind kind, LValue ptr, LValue base)
{
-#if CPU(ARM64E)
- if (kind == Gigacage::Primitive) {
- LValue size = m_out.load32(base, m_heaps.JSArrayBufferView_length);
- ptr = untagArrayPtr(ptr, size);
- }
-#else
- UNUSED_PARAM(kind);
- UNUSED_PARAM(base);
-#endif
-
#if GIGACAGE_ENABLED
- UNUSED_PARAM(base);
if (!Gigacage::isEnabled(kind))
return ptr;
@@ -14206,7 +14195,7 @@
LValue result = m_out.add(masked, basePtr);
#if CPU(ARM64E)
- {
+ if (kind == Gigacage::Primitive) {
PatchpointValue* merge = m_out.patchpoint(pointerType());
merge->append(result, B3::ValueRep(B3::ValueRep::SomeLateRegister));
merge->appendSomeRegister(ptr);
@@ -14214,9 +14203,12 @@
jit.move(params[2].gpr(), params[0].gpr());
jit.bitFieldInsert64(params[1].gpr(), 0, 64 - MacroAssembler::numberOfPACBits, params[0].gpr());
});
- result = merge;
+
+ LValue size = m_out.load32(base, m_heaps.JSArrayBufferView_length);
+ result = untagArrayPtr(merge, size);
}
-#endif
+#endif // CPU(ARM64E)
+
// Make sure that B3 doesn't try to do smart reassociation of these pointer bits.
// FIXME: In an ideal world, B3 would not do harmful reassociations, and if it did, it would be able
// to undo them during constant hoisting and regalloc. As it stands, if you remove this then Octane
@@ -14230,6 +14222,9 @@
// https://bugs.webkit.org/show_bug.cgi?id=175493
return m_out.opaque(result);
#endif
+
+ UNUSED_PARAM(kind);
+ UNUSED_PARAM(base);
return ptr;
}
Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (247100 => 247101)
--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h 2019-07-03 20:25:14 UTC (rev 247101)
@@ -1586,42 +1586,41 @@
// length may be the same register as scratch.
void cageConditionally(Gigacage::Kind kind, GPRReg storage, GPRReg length, GPRReg scratch)
{
+#if GIGACAGE_ENABLED
+ if (Gigacage::isEnabled(kind)) {
+ if (kind != Gigacage::Primitive || Gigacage::isDisablingPrimitiveGigacageDisabled())
+ cageWithoutUntagging(kind, storage);
+ else {
#if CPU(ARM64E)
+ if (length == scratch)
+ scratch = getCachedMemoryTempRegisterIDAndInvalidate();
+#endif
+ loadPtr(&Gigacage::basePtr(kind), scratch);
+ Jump done = branchTest64(Zero, scratch);
+#if CPU(ARM64E)
+ GPRReg tempReg = getCachedDataTempRegisterIDAndInvalidate();
+ move(storage, tempReg);
+ ASSERT(LogicalImmediate::create64(Gigacage::mask(kind)).isValid());
+ andPtr(TrustedImmPtr(Gigacage::mask(kind)), tempReg);
+ addPtr(scratch, tempReg);
+ bitFieldInsert64(tempReg, 0, 64 - numberOfPACBits, storage);
+#else
+ andPtr(TrustedImmPtr(Gigacage::mask(kind)), storage);
+ addPtr(scratch, storage);
+#endif // CPU(ARM64E)
+ done.link(this);
+ }
+ }
+#endif
+
+#if CPU(ARM64E)
if (kind == Gigacage::Primitive)
untagArrayPtr(length, storage);
-#else
+#endif
UNUSED_PARAM(kind);
UNUSED_PARAM(storage);
UNUSED_PARAM(length);
-#endif
-
-#if GIGACAGE_ENABLED
- if (!Gigacage::isEnabled(kind))
- return;
-
- if (kind != Gigacage::Primitive || Gigacage::isDisablingPrimitiveGigacageDisabled())
- cageWithoutUntagging(kind, storage);
- else {
- loadPtr(&Gigacage::basePtr(kind), scratch);
- Jump done = branchTestPtr(Zero, scratch);
-#if CPU(ARM64E)
- auto tempReg = getCachedMemoryTempRegisterIDAndInvalidate();
- move(storage, tempReg);
- andPtr(TrustedImmPtr(Gigacage::mask(kind)), tempReg);
- addPtr(scratch, tempReg);
- bitFieldInsert64(tempReg, 0, 64 - numberOfPACBits, storage);
-#else
- andPtr(TrustedImmPtr(Gigacage::mask(kind)), storage);
- addPtr(scratch, storage);
-#endif
- done.link(this);
-
-
- }
-#else
UNUSED_PARAM(scratch);
-#endif
-
}
void emitComputeButterflyIndexingMask(GPRReg vectorLengthGPR, GPRReg scratchGPR, GPRReg resultGPR)
Modified: trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm (247100 => 247101)
--- trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/_javascript_Core/llint/LowLevelInterpreter64.asm 2019-07-03 20:25:14 UTC (rev 247101)
@@ -422,30 +422,29 @@
end)
end
-macro uncage(basePtr, mask, ptr, scratchOrLength)
+macro cage(basePtr, mask, ptr, scratch)
if GIGACAGE_ENABLED and not (C_LOOP or C_LOOP_WIN)
- loadp basePtr, scratchOrLength
- btpz scratchOrLength, .done
+ loadp basePtr, scratch
+ btpz scratch, .done
andp mask, ptr
- addp scratchOrLength, ptr
+ addp scratch, ptr
.done:
end
end
-macro loadCagedPrimitive(source, dest, scratchOrLength)
- loadp source, dest
+macro cagedPrimitive(ptr, length, scratch, scratch2)
if ARM64E
- const result = t7
- untagArrayPtr scratchOrLength, dest
- move dest, result
+ const source = scratch2
+ move ptr, scratch2
else
- const result = dest
+ const source = ptr
end
if GIGACAGE_ENABLED
- uncage(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr Gigacage::primitiveGigacageMask, result, scratchOrLength)
+ cage(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr Gigacage::primitiveGigacageMask, source, scratch)
if ARM64E
const numberOfPACBits = constexpr MacroAssembler::numberOfPACBits
- bfiq result, 0, 64 - numberOfPACBits, dest
+ bfiq scratch2, 0, 64 - numberOfPACBits, ptr
+ untagArrayPtr length, ptr
end
end
end
@@ -452,7 +451,7 @@
macro loadCagedJSValue(source, dest, scratchOrLength)
loadp source, dest
- uncage(_g_gigacageBasePtrs + Gigacage::BasePtrs::jsValue, constexpr Gigacage::jsValueGigacageMask, dest, scratchOrLength)
+ cage(_g_gigacageBasePtrs + Gigacage::BasePtrs::jsValue, constexpr Gigacage::jsValueGigacageMask, dest, scratchOrLength)
end
macro loadVariable(get, fieldName, valueReg)
@@ -1522,15 +1521,17 @@
# Sweet, now we know that we have a typed array. Do some basic things now.
if ARM64E
- const scratchOrLength = t6
- loadi JSArrayBufferView::m_length[t0], scratchOrLength
- biaeq t1, scratchOrLength, .opGetByValSlow
+ const length = t6
+ const scratch = t7
+ loadi JSArrayBufferView::m_length[t0], length
+ biaeq t1, length, .opGetByValSlow
else
- const scratchOrLength = t0
+ # length and scratch are intentionally undefined on this branch because they are not used on other platforms.
biaeq t1, JSArrayBufferView::m_length[t0], .opGetByValSlow
end
- loadCagedPrimitive(JSArrayBufferView::m_vector[t0], t3, scratchOrLength)
+ loadp JSArrayBufferView::m_vector[t0], t3
+ cagedPrimitive(t3, length, t0, scratch)
# Now bisect through the various types:
# Int8ArrayType,
Modified: trunk/Source/WTF/ChangeLog (247100 => 247101)
--- trunk/Source/WTF/ChangeLog 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/WTF/ChangeLog 2019-07-03 20:25:14 UTC (rev 247101)
@@ -1,3 +1,15 @@
+2019-07-03 Keith Miller <[email protected]>
+
+ PACCage should first cage leaving PAC bits intact then authenticate
+ https://bugs.webkit.org/show_bug.cgi?id=199372
+
+ Reviewed by Saam Barati.
+
+ * wtf/CagedPtr.h:
+ (WTF::CagedPtr::get const):
+ (WTF::CagedPtr::getMayBeNull const):
+ (WTF::CagedPtr::mergePointers):
+
2019-07-03 Ryan Haddad <[email protected]>
Unreviewed, rolling out r246616.
Modified: trunk/Source/WTF/wtf/CagedPtr.h (247100 => 247101)
--- trunk/Source/WTF/wtf/CagedPtr.h 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/WTF/wtf/CagedPtr.h 2019-07-03 20:25:14 UTC (rev 247101)
@@ -39,6 +39,8 @@
class CagedPtr {
public:
static constexpr Gigacage::Kind kind = passedKind;
+ static constexpr unsigned numberOfPACBits = 25;
+ static constexpr uintptr_t nonPACBitsMask = (1ull << ((sizeof(T*) * CHAR_BIT) - numberOfPACBits)) - 1;
CagedPtr() : CagedPtr(nullptr) { }
CagedPtr(std::nullptr_t)
@@ -49,20 +51,23 @@
: m_ptr(shouldTag ? tagArrayPtr(ptr, size) : ptr)
{ }
-
T* get(unsigned size) const
{
ASSERT(m_ptr);
T* ptr = PtrTraits::unwrap(m_ptr);
- T* untaggedPtr = shouldTag ? untagArrayPtr(ptr, size) : ptr;
- return mergePointers(untaggedPtr, Gigacage::caged(kind, ptr));
+ T* cagedPtr = Gigacage::caged(kind, ptr);
+ T* untaggedPtr = shouldTag ? untagArrayPtr(mergePointers(ptr, cagedPtr), size) : cagedPtr;
+ return untaggedPtr;
}
T* getMayBeNull(unsigned size) const
{
T* ptr = PtrTraits::unwrap(m_ptr);
- T* untaggedPtr = shouldTag ? untagArrayPtr(ptr, size) : ptr;
- return mergePointers(untaggedPtr, Gigacage::cagedMayBeNull(kind, ptr));
+ if (!removeArrayPtrTag(ptr))
+ return nullptr;
+ T* cagedPtr = Gigacage::caged(kind, ptr);
+ T* untaggedPtr = shouldTag ? untagArrayPtr(mergePointers(ptr, cagedPtr), size) : cagedPtr;
+ return untaggedPtr;
}
T* getUnsafe() const
@@ -124,11 +129,14 @@
}
protected:
- static inline T* mergePointers(const T* untaggedPtr, const T* uncagedPtr)
+ static inline T* mergePointers(T* sourcePtr, T* cagedPtr)
{
- constexpr unsigned numberOfPACBits = 25;
- constexpr uintptr_t mask = (1ull << ((sizeof(T*) * CHAR_BIT) - numberOfPACBits)) - 1;
- return reinterpret_cast<T*>((reinterpret_cast<uintptr_t>(untaggedPtr) & ~mask) | (reinterpret_cast<uintptr_t>(uncagedPtr) & mask));
+#if CPU(ARM64E)
+ return reinterpret_cast<T*>((reinterpret_cast<uintptr_t>(sourcePtr) & ~nonPACBitsMask) | (reinterpret_cast<uintptr_t>(cagedPtr) & nonPACBitsMask));
+#else
+ UNUSED_PARAM(sourcePtr);
+ return cagedPtr;
+#endif
}
typename PtrTraits::StorageType m_ptr;
Modified: trunk/Source/bmalloc/ChangeLog (247100 => 247101)
--- trunk/Source/bmalloc/ChangeLog 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/bmalloc/ChangeLog 2019-07-03 20:25:14 UTC (rev 247101)
@@ -1,3 +1,13 @@
+2019-07-03 Keith Miller <[email protected]>
+
+ PACCage should first cage leaving PAC bits intact then authenticate
+ https://bugs.webkit.org/show_bug.cgi?id=199372
+
+ Reviewed by Saam Barati.
+
+ * bmalloc/ProcessCheck.mm:
+ (bmalloc::shouldProcessUnconditionallyUseBmalloc):
+
2019-07-02 Commit Queue <[email protected]>
Unreviewed, rolling out r247041.
Modified: trunk/Source/bmalloc/bmalloc/ProcessCheck.mm (247100 => 247101)
--- trunk/Source/bmalloc/bmalloc/ProcessCheck.mm 2019-07-03 19:59:02 UTC (rev 247100)
+++ trunk/Source/bmalloc/bmalloc/ProcessCheck.mm 2019-07-03 20:25:14 UTC (rev 247101)
@@ -66,7 +66,9 @@
result = contains(@"com.apple.WebKit") || contains(@"safari");
} else {
NSString *processName = [[NSProcessInfo processInfo] processName];
- result = [processName isEqualToString:@"jsc"] || [processName isEqualToString:@"wasm"];
+ result = [processName isEqualToString:@"jsc"]
+ || [processName isEqualToString:@"wasm"]
+ || [processName hasPrefix:@"test"];
}
});