Changeset 247101 in webkit
- Timestamp:
- Jul 3, 2019 1:25:14 PM (5 years ago)
- Location:
- trunk/Source
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r247097 r247101 1 2019-07-03 Keith Miller <keith_miller@apple.com> 2 3 PACCage should first cage leaving PAC bits intact then authenticate 4 https://bugs.webkit.org/show_bug.cgi?id=199372 5 6 Reviewed by Saam Barati. 7 8 This ordering prevents someone from taking a signed pointer from 9 outside the gigacage and using it in a struct that expects a caged 10 pointer. Previously, the PACCaging just double checked that the PAC 11 bits were valid for the original pointer. 12 13 14 +---------------------------+ 15 | | | | 16 | "PAC" | "base" | "offset" +----+ 17 | | | | | 18 +---------------------------+ | Caging 19 | | 20 | | 21 | v 22 | +---------------------------+ 23 | | | | | 24 | Bit Merge | 00000 | base | "offset" | 25 | | | | | 26 | +---------------------------+ 27 | | 28 | | 29 v | Bit Merge 30 +---------------------------+ | 31 | | | | | 32 | "PAC" | base | "offset" +<--------+ 33 | | | | 34 +---------------------------+ 35 | 36 | 37 | Authenticate 38 | 39 v 40 +---------------------------+ 41 | | | | 42 | Auth | base | "offset" | 43 | | | | 44 +---------------------------+ 45 46 The above ascii art graph shows how the PACCage system works. The 47 key take away is that even if someone passes in a valid, signed 48 pointer outside the cage it will still fail to authenticate as the 49 "base" bits will change before authentication. 50 51 52 * assembler/MacroAssemblerARM64E.h: 53 * assembler/testmasm.cpp: 54 (JSC::testCagePreservesPACFailureBit): 55 * ftl/FTLLowerDFGToB3.cpp: 56 (JSC::FTL::DFG::LowerDFGToB3::caged): 57 * jit/AssemblyHelpers.h: 58 (JSC::AssemblyHelpers::cageConditionally): 59 * llint/LowLevelInterpreter64.asm: 60 1 61 2019-07-03 Paulo Matos <pmatos@igalia.com> 2 62 -
trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64E.h
r247079 r247101 41 41 public: 42 42 static constexpr unsigned numberOfPACBits = 25; 43 static constexpr uintptr_t nonPACBitsMask = (1ull << (64 - numberOfPACBits)) - 1; 43 44 44 45 ALWAYS_INLINE void tagReturnAddress() -
trunk/Source/JavaScriptCore/assembler/testmasm.cpp
r247079 r247101 1016 1016 static void testCagePreservesPACFailureBit() 1017 1017 { 1018 #if GIGACAGE_ENABLED 1019 ASSERT(!Gigacage::isDisablingPrimitiveGigacageDisabled()); 1018 1020 auto cage = compile([] (CCallHelpers& jit) { 1019 1021 jit.emitFunctionPrologue(); … … 1026 1028 void* ptr = Gigacage::tryMalloc(Gigacage::Primitive, 1); 1027 1029 void* taggedPtr = tagArrayPtr(ptr, 1); 1028 dataLogLn("starting test"); 1030 ASSERT(hasOneBitSet(Gigacage::size(Gigacage::Primitive) << 2)); 1031 void* notCagedPtr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(ptr) + (Gigacage::size(Gigacage::Primitive) << 2)); 1032 CHECK_NOT_EQ(Gigacage::caged(Gigacage::Primitive, notCagedPtr), notCagedPtr); 1033 void* taggedNotCagedPtr = tagArrayPtr(notCagedPtr, 1); 1034 1029 1035 if (isARM64E()) { 1030 1036 // FIXME: This won't work if authentication failures trap but I don't know how to test for that right now. 1031 1037 CHECK_NOT_EQ(invoke<void*>(cage, taggedPtr, 2), ptr); 1038 CHECK_EQ(invoke<void*>(cage, taggedNotCagedPtr, 1), untagArrayPtr(taggedPtr, 2)); 1032 1039 } else 1033 1040 CHECK_EQ(invoke<void*>(cage, taggedPtr, 2), ptr); … … 1043 1050 }); 1044 1051 1052 CHECK_EQ(invoke<void*>(cageWithoutAuthentication, taggedPtr), taggedPtr); 1045 1053 if (isARM64E()) { 1046 1054 // FIXME: This won't work if authentication failures trap but I don't know how to test for that right now. 1047 CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, untagArrayPtr(taggedPtr, 2)), ptr); 1048 } else 1049 CHECK_EQ(invoke<void*>(cageWithoutAuthentication, untagArrayPtr(taggedPtr, 2)), ptr); 1050 1051 CHECK_EQ(untagArrayPtr(taggedPtr, 1), ptr); 1052 CHECK_EQ(invoke<void*>(cageWithoutAuthentication, untagArrayPtr(taggedPtr, 1)), ptr); 1055 CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), taggedNotCagedPtr); 1056 CHECK_NOT_EQ(untagArrayPtr(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), 1), notCagedPtr); 1057 CHECK_NOT_EQ(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), taggedPtr); 1058 CHECK_NOT_EQ(untagArrayPtr(invoke<void*>(cageWithoutAuthentication, taggedNotCagedPtr), 1), ptr); 1059 } 1053 1060 1054 1061 Gigacage::free(Gigacage::Primitive, ptr); 1062 #endif 1055 1063 } 1056 1064 -
trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
r247079 r247101 14178 14178 LValue caged(Gigacage::Kind kind, LValue ptr, LValue base) 14179 14179 { 14180 #if CPU(ARM64E)14181 if (kind == Gigacage::Primitive) {14182 LValue size = m_out.load32(base, m_heaps.JSArrayBufferView_length);14183 ptr = untagArrayPtr(ptr, size);14184 }14185 #else14186 UNUSED_PARAM(kind);14187 UNUSED_PARAM(base);14188 #endif14189 14190 14180 #if GIGACAGE_ENABLED 14191 UNUSED_PARAM(base);14192 14181 if (!Gigacage::isEnabled(kind)) 14193 14182 return ptr; … … 14207 14196 14208 14197 #if CPU(ARM64E) 14209 {14198 if (kind == Gigacage::Primitive) { 14210 14199 PatchpointValue* merge = m_out.patchpoint(pointerType()); 14211 14200 merge->append(result, B3::ValueRep(B3::ValueRep::SomeLateRegister)); … … 14215 14204 jit.bitFieldInsert64(params[1].gpr(), 0, 64 - MacroAssembler::numberOfPACBits, params[0].gpr()); 14216 14205 }); 14217 result = merge; 14218 } 14219 #endif 14206 14207 LValue size = m_out.load32(base, m_heaps.JSArrayBufferView_length); 14208 result = untagArrayPtr(merge, size); 14209 } 14210 #endif // CPU(ARM64E) 14211 14220 14212 // Make sure that B3 doesn't try to do smart reassociation of these pointer bits. 14221 14213 // FIXME: In an ideal world, B3 would not do harmful reassociations, and if it did, it would be able … … 14231 14223 return m_out.opaque(result); 14232 14224 #endif 14225 14226 UNUSED_PARAM(kind); 14227 UNUSED_PARAM(base); 14233 14228 return ptr; 14234 14229 } -
trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h
r247079 r247101 1587 1587 void cageConditionally(Gigacage::Kind kind, GPRReg storage, GPRReg length, GPRReg scratch) 1588 1588 { 1589 #if GIGACAGE_ENABLED 1590 if (Gigacage::isEnabled(kind)) { 1591 if (kind != Gigacage::Primitive || Gigacage::isDisablingPrimitiveGigacageDisabled()) 1592 cageWithoutUntagging(kind, storage); 1593 else { 1594 #if CPU(ARM64E) 1595 if (length == scratch) 1596 scratch = getCachedMemoryTempRegisterIDAndInvalidate(); 1597 #endif 1598 loadPtr(&Gigacage::basePtr(kind), scratch); 1599 Jump done = branchTest64(Zero, scratch); 1600 #if CPU(ARM64E) 1601 GPRReg tempReg = getCachedDataTempRegisterIDAndInvalidate(); 1602 move(storage, tempReg); 1603 ASSERT(LogicalImmediate::create64(Gigacage::mask(kind)).isValid()); 1604 andPtr(TrustedImmPtr(Gigacage::mask(kind)), tempReg); 1605 addPtr(scratch, tempReg); 1606 bitFieldInsert64(tempReg, 0, 64 - numberOfPACBits, storage); 1607 #else 1608 andPtr(TrustedImmPtr(Gigacage::mask(kind)), storage); 1609 addPtr(scratch, storage); 1610 #endif // CPU(ARM64E) 1611 done.link(this); 1612 } 1613 } 1614 #endif 1615 1589 1616 #if CPU(ARM64E) 1590 1617 if (kind == Gigacage::Primitive) 1591 1618 untagArrayPtr(length, storage); 1592 #e lse1619 #endif 1593 1620 UNUSED_PARAM(kind); 1594 1621 UNUSED_PARAM(storage); 1595 1622 UNUSED_PARAM(length); 1596 #endif1597 1598 #if GIGACAGE_ENABLED1599 if (!Gigacage::isEnabled(kind))1600 return;1601 1602 if (kind != Gigacage::Primitive || Gigacage::isDisablingPrimitiveGigacageDisabled())1603 cageWithoutUntagging(kind, storage);1604 else {1605 loadPtr(&Gigacage::basePtr(kind), scratch);1606 Jump done = branchTestPtr(Zero, scratch);1607 #if CPU(ARM64E)1608 auto tempReg = getCachedMemoryTempRegisterIDAndInvalidate();1609 move(storage, tempReg);1610 andPtr(TrustedImmPtr(Gigacage::mask(kind)), tempReg);1611 addPtr(scratch, tempReg);1612 bitFieldInsert64(tempReg, 0, 64 - numberOfPACBits, storage);1613 #else1614 andPtr(TrustedImmPtr(Gigacage::mask(kind)), storage);1615 addPtr(scratch, storage);1616 #endif1617 done.link(this);1618 1619 1620 }1621 #else1622 1623 UNUSED_PARAM(scratch); 1623 #endif1624 1625 1624 } 1626 1625 -
trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
r247079 r247101 423 423 end 424 424 425 macro uncage(basePtr, mask, ptr, scratchOrLength)425 macro cage(basePtr, mask, ptr, scratch) 426 426 if GIGACAGE_ENABLED and not (C_LOOP or C_LOOP_WIN) 427 loadp basePtr, scratch OrLength428 btpz scratch OrLength, .done427 loadp basePtr, scratch 428 btpz scratch, .done 429 429 andp mask, ptr 430 addp scratch OrLength, ptr430 addp scratch, ptr 431 431 .done: 432 432 end 433 433 end 434 434 435 macro loadCagedPrimitive(source, dest, scratchOrLength) 436 loadp source, dest 435 macro cagedPrimitive(ptr, length, scratch, scratch2) 437 436 if ARM64E 438 const result = t7 439 untagArrayPtr scratchOrLength, dest 440 move dest, result 437 const source = scratch2 438 move ptr, scratch2 441 439 else 442 const result = dest440 const source = ptr 443 441 end 444 442 if GIGACAGE_ENABLED 445 uncage(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr Gigacage::primitiveGigacageMask, result, scratchOrLength)443 cage(_g_gigacageBasePtrs + Gigacage::BasePtrs::primitive, constexpr Gigacage::primitiveGigacageMask, source, scratch) 446 444 if ARM64E 447 445 const numberOfPACBits = constexpr MacroAssembler::numberOfPACBits 448 bfiq result, 0, 64 - numberOfPACBits, dest 446 bfiq scratch2, 0, 64 - numberOfPACBits, ptr 447 untagArrayPtr length, ptr 449 448 end 450 449 end … … 453 452 macro loadCagedJSValue(source, dest, scratchOrLength) 454 453 loadp source, dest 455 uncage(_g_gigacageBasePtrs + Gigacage::BasePtrs::jsValue, constexpr Gigacage::jsValueGigacageMask, dest, scratchOrLength)454 cage(_g_gigacageBasePtrs + Gigacage::BasePtrs::jsValue, constexpr Gigacage::jsValueGigacageMask, dest, scratchOrLength) 456 455 end 457 456 … … 1523 1522 1524 1523 if ARM64E 1525 const scratchOrLength = t6 1526 loadi JSArrayBufferView::m_length[t0], scratchOrLength 1527 biaeq t1, scratchOrLength, .opGetByValSlow 1524 const length = t6 1525 const scratch = t7 1526 loadi JSArrayBufferView::m_length[t0], length 1527 biaeq t1, length, .opGetByValSlow 1528 1528 else 1529 const scratchOrLength = t01529 # length and scratch are intentionally undefined on this branch because they are not used on other platforms. 1530 1530 biaeq t1, JSArrayBufferView::m_length[t0], .opGetByValSlow 1531 1531 end 1532 1532 1533 loadCagedPrimitive(JSArrayBufferView::m_vector[t0], t3, scratchOrLength) 1533 loadp JSArrayBufferView::m_vector[t0], t3 1534 cagedPrimitive(t3, length, t0, scratch) 1534 1535 1535 1536 # Now bisect through the various types: -
trunk/Source/WTF/ChangeLog
r247095 r247101 1 2019-07-03 Keith Miller <keith_miller@apple.com> 2 3 PACCage should first cage leaving PAC bits intact then authenticate 4 https://bugs.webkit.org/show_bug.cgi?id=199372 5 6 Reviewed by Saam Barati. 7 8 * wtf/CagedPtr.h: 9 (WTF::CagedPtr::get const): 10 (WTF::CagedPtr::getMayBeNull const): 11 (WTF::CagedPtr::mergePointers): 12 1 13 2019-07-03 Ryan Haddad <ryanhaddad@apple.com> 2 14 -
trunk/Source/WTF/wtf/CagedPtr.h
r247079 r247101 40 40 public: 41 41 static constexpr Gigacage::Kind kind = passedKind; 42 static constexpr unsigned numberOfPACBits = 25; 43 static constexpr uintptr_t nonPACBitsMask = (1ull << ((sizeof(T*) * CHAR_BIT) - numberOfPACBits)) - 1; 42 44 43 45 CagedPtr() : CagedPtr(nullptr) { } … … 50 52 { } 51 53 52 53 54 T* get(unsigned size) const 54 55 { 55 56 ASSERT(m_ptr); 56 57 T* ptr = PtrTraits::unwrap(m_ptr); 57 T* untaggedPtr = shouldTag ? untagArrayPtr(ptr, size) : ptr; 58 return mergePointers(untaggedPtr, Gigacage::caged(kind, ptr)); 58 T* cagedPtr = Gigacage::caged(kind, ptr); 59 T* untaggedPtr = shouldTag ? untagArrayPtr(mergePointers(ptr, cagedPtr), size) : cagedPtr; 60 return untaggedPtr; 59 61 } 60 62 … … 62 64 { 63 65 T* ptr = PtrTraits::unwrap(m_ptr); 64 T* untaggedPtr = shouldTag ? untagArrayPtr(ptr, size) : ptr; 65 return mergePointers(untaggedPtr, Gigacage::cagedMayBeNull(kind, ptr)); 66 if (!removeArrayPtrTag(ptr)) 67 return nullptr; 68 T* cagedPtr = Gigacage::caged(kind, ptr); 69 T* untaggedPtr = shouldTag ? untagArrayPtr(mergePointers(ptr, cagedPtr), size) : cagedPtr; 70 return untaggedPtr; 66 71 } 67 72 … … 125 130 126 131 protected: 127 static inline T* mergePointers( const T* untaggedPtr, const T* uncagedPtr)132 static inline T* mergePointers(T* sourcePtr, T* cagedPtr) 128 133 { 129 constexpr unsigned numberOfPACBits = 25; 130 constexpr uintptr_t mask = (1ull << ((sizeof(T*) * CHAR_BIT) - numberOfPACBits)) - 1; 131 return reinterpret_cast<T*>((reinterpret_cast<uintptr_t>(untaggedPtr) & ~mask) | (reinterpret_cast<uintptr_t>(uncagedPtr) & mask)); 134 #if CPU(ARM64E) 135 return reinterpret_cast<T*>((reinterpret_cast<uintptr_t>(sourcePtr) & ~nonPACBitsMask) | (reinterpret_cast<uintptr_t>(cagedPtr) & nonPACBitsMask)); 136 #else 137 UNUSED_PARAM(sourcePtr); 138 return cagedPtr; 139 #endif 132 140 } 133 141 -
trunk/Source/bmalloc/ChangeLog
r247079 r247101 1 2019-07-03 Keith Miller <keith_miller@apple.com> 2 3 PACCage should first cage leaving PAC bits intact then authenticate 4 https://bugs.webkit.org/show_bug.cgi?id=199372 5 6 Reviewed by Saam Barati. 7 8 * bmalloc/ProcessCheck.mm: 9 (bmalloc::shouldProcessUnconditionallyUseBmalloc): 10 1 11 2019-07-02 Commit Queue <commit-queue@webkit.org> 2 12 -
trunk/Source/bmalloc/bmalloc/ProcessCheck.mm
r247079 r247101 67 67 } else { 68 68 NSString *processName = [[NSProcessInfo processInfo] processName]; 69 result = [processName isEqualToString:@"jsc"] || [processName isEqualToString:@"wasm"]; 69 result = [processName isEqualToString:@"jsc"] 70 || [processName isEqualToString:@"wasm"] 71 || [processName hasPrefix:@"test"]; 70 72 } 71 73 });
Note: See TracChangeset
for help on using the changeset viewer.