[ARM64E] Harden the diversity of the DOMJIT::Signature::unsafeFunction pointer.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 3 Aug 2019 00:31:31 +0000 (00:31 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 3 Aug 2019 00:31:31 +0000 (00:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200292
<rdar://problem/53706881>

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Previously, DOMJIT::Signature::functionWithoutTypeCheck was signed as a C function
pointer.  We can do better by signing it like a vtbl function pointer.

No new tests needed.  The DOMJIT mechanism is covered by existing tests.

I also manually confirmed that DOMJIT::Signature::functionWithoutTypeCheck is signed
exactly as expected by reading its bits out of memory (not letting Clang have a
chance to resign it into a C function pointer) and comparing it against manually
signed bits with the expected diversifier.

* assembler/MacroAssemblerCodeRef.h:
(JSC::CFunctionPtr::CFunctionPtr):
(JSC::CFunctionPtr::get const):
(JSC::CFunctionPtr::address const):
(JSC::CFunctionPtr::operator bool const):
(JSC::CFunctionPtr::operator! const):
(JSC::CFunctionPtr::operator== const):
(JSC::CFunctionPtr::operator!= const):

- Introduce a CFunctionPtr abstraction that is used to hold pointers to C functions.
  It can instantiated in 4 ways:

  1. The default constructor.
  2. A constructor that takes a nullptr_t.

     These 2 forms will instantiate a CFunctionPtr with a nullptr.

  3. A constructor that takes the name of a function.
  4. A constructor that takes a function pointer.

      Form 3 already knows that we're initializing with a real function, and
      that Clang will give it to use signed as a C function pointer.  So, it
      doesn't do any assertions.  This form is useful for initializing CFunctionPtrs
      embedded in const data structures.

      Form 4 is an explicit constructor that takes an arbitrary function
      pointer, but does not know if that pointer is already signed as a C function
      pointer.  Hence, this form will do a RELEASE_ASSERT that the given function
      pointer is actually signed as a C function pointer.

  Once instantiated, we are guaranteed that a C function pointer is either null
  or contains a signed C function pointer.

* domjit/DOMJITSignature.h:
(JSC::DOMJIT::Signature::Signature):
- Sign functionWithoutTypeCheck as WTF_VTBL_FUNCPTR_PTRAUTH(DOMJITFunctionPtrTag).

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileCallDOM):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileCallDOM):
- Use the new CFunctionPtr to document that the retrieved signature->functionWithoutTypeCheck
  is signed as a C function pointer.

* runtime/ClassInfo.h:
- Update MethodTable to sign its function pointers using the new WTF_VTBL_FUNCPTR_PTRAUTH_STR
  to be consistent.  No longer need to roll its own PTRAUTH macro.

* runtime/JSCPtrTag.h:
- Add DOMJITFunctionPtrTag.

* tools/JSDollarVM.cpp:
- Update to work with the new DOMJIT::Signature constructor.

Source/WebCore:

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateImplementation):
- Update to work with the new DOMJIT::Signature constructor.

* bindings/scripts/test/JS/JSTestDOMJIT.cpp:
- Re-base test results.

Source/WTF:

* wtf/PtrTag.h:
- Introducing WTF_VTBL_FUNCPTR_PTRAUTH and WTF_VTBL_FUNCPTR_PTRAUTH_STR macros for
  defining vtbl function pointer style pointer signing modifier.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@248192 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/domjit/DOMJITSignature.h
Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp
Source/JavaScriptCore/runtime/ClassInfo.h
Source/JavaScriptCore/runtime/JSCPtrTag.h
Source/JavaScriptCore/tools/JSDollarVM.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/PtrTag.h
Source/WebCore/ChangeLog
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestDOMJIT.cpp

index 7301702..c0bb7e0 100644 (file)
@@ -1,3 +1,75 @@
+2019-08-02  Mark Lam  <mark.lam@apple.com>
+
+        [ARM64E] Harden the diversity of the DOMJIT::Signature::unsafeFunction pointer.
+        https://bugs.webkit.org/show_bug.cgi?id=200292
+        <rdar://problem/53706881>
+
+        Reviewed by Geoffrey Garen.
+
+        Previously, DOMJIT::Signature::functionWithoutTypeCheck was signed as a C function
+        pointer.  We can do better by signing it like a vtbl function pointer.
+
+        No new tests needed.  The DOMJIT mechanism is covered by existing tests.
+
+        I also manually confirmed that DOMJIT::Signature::functionWithoutTypeCheck is signed
+        exactly as expected by reading its bits out of memory (not letting Clang have a
+        chance to resign it into a C function pointer) and comparing it against manually
+        signed bits with the expected diversifier.
+
+        * assembler/MacroAssemblerCodeRef.h:
+        (JSC::CFunctionPtr::CFunctionPtr):
+        (JSC::CFunctionPtr::get const):
+        (JSC::CFunctionPtr::address const):
+        (JSC::CFunctionPtr::operator bool const):
+        (JSC::CFunctionPtr::operator! const):
+        (JSC::CFunctionPtr::operator== const):
+        (JSC::CFunctionPtr::operator!= const):
+
+        - Introduce a CFunctionPtr abstraction that is used to hold pointers to C functions.
+          It can instantiated in 4 ways:
+
+          1. The default constructor.
+          2. A constructor that takes a nullptr_t.
+
+             These 2 forms will instantiate a CFunctionPtr with a nullptr.
+
+          3. A constructor that takes the name of a function.
+          4. A constructor that takes a function pointer.
+
+              Form 3 already knows that we're initializing with a real function, and
+              that Clang will give it to use signed as a C function pointer.  So, it
+              doesn't do any assertions.  This form is useful for initializing CFunctionPtrs
+              embedded in const data structures.
+
+              Form 4 is an explicit constructor that takes an arbitrary function
+              pointer, but does not know if that pointer is already signed as a C function
+              pointer.  Hence, this form will do a RELEASE_ASSERT that the given function
+              pointer is actually signed as a C function pointer.
+
+          Once instantiated, we are guaranteed that a C function pointer is either null
+          or contains a signed C function pointer.
+
+        * domjit/DOMJITSignature.h:
+        (JSC::DOMJIT::Signature::Signature):
+        - Sign functionWithoutTypeCheck as WTF_VTBL_FUNCPTR_PTRAUTH(DOMJITFunctionPtrTag).
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCallDOM):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileCallDOM):
+        - Use the new CFunctionPtr to document that the retrieved signature->functionWithoutTypeCheck
+          is signed as a C function pointer.
+
+        * runtime/ClassInfo.h:
+        - Update MethodTable to sign its function pointers using the new WTF_VTBL_FUNCPTR_PTRAUTH_STR
+          to be consistent.  No longer need to roll its own PTRAUTH macro.
+
+        * runtime/JSCPtrTag.h:
+        - Add DOMJITFunctionPtrTag.
+
+        * tools/JSDollarVM.cpp:
+        - Update to work with the new DOMJIT::Signature constructor.
+
 2019-08-02  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] Support WebAssembly in SamplingProfiler
index 54658dd..d57bec0 100644 (file)
@@ -58,6 +58,71 @@ template<PtrTag> class MacroAssemblerCodePtr;
 
 enum OpcodeID : unsigned;
 
+// CFunctionPtr can only be used to hold C/C++ functions.
+class CFunctionPtr {
+public:
+    using Ptr = void(*)();
+
+    CFunctionPtr() { }
+    CFunctionPtr(std::nullptr_t) { }
+
+    template<typename ReturnType, typename... Arguments>
+    constexpr CFunctionPtr(ReturnType(&ptr)(Arguments...))
+        : m_ptr(reinterpret_cast<Ptr>(&ptr))
+    { }
+
+    template<typename ReturnType, typename... Arguments>
+    explicit CFunctionPtr(ReturnType(*ptr)(Arguments...))
+        : m_ptr(reinterpret_cast<Ptr>(ptr))
+    {
+        assertIsCFunctionPtr(m_ptr);
+    }
+
+    // MSVC doesn't seem to treat functions with different calling conventions as
+    // different types; these methods are already defined for fastcall, below.
+#if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
+    template<typename ReturnType, typename... Arguments>
+    constexpr CFunctionPtr(ReturnType(CDECL &ptr)(Arguments...))
+        : m_ptr(reinterpret_cast<Ptr>(&ptr))
+    { }
+
+    template<typename ReturnType, typename... Arguments>
+    explicit CFunctionPtr(ReturnType(CDECL *ptr)(Arguments...))
+        : m_ptr(reinterpret_cast<Ptr>(ptr))
+    {
+        assertIsCFunctionPtr(m_ptr);
+    }
+
+#endif // CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS)
+
+#if COMPILER_SUPPORTS(FASTCALL_CALLING_CONVENTION)
+    template<typename ReturnType, typename... Arguments>
+    constexpr CFunctionPtr(ReturnType(FASTCALL &ptr)(Arguments...))
+        : m_ptr(reinterpret_cast<Ptr>(&ptr))
+    { }
+
+    template<typename ReturnType, typename... Arguments>
+    explicit CFunctionPtr(ReturnType(FASTCALL *ptr)(Arguments...))
+        : m_ptr(reinterpret_cast<Ptr>(ptr))
+    {
+        assertIsCFunctionPtr(m_ptr);
+    }
+#endif // COMPILER_SUPPORTS(FASTCALL_CALLING_CONVENTION)
+
+    constexpr Ptr get() const { return m_ptr; }
+    void* address() const { return reinterpret_cast<void*>(m_ptr); }
+
+    explicit operator bool() const { return !!m_ptr; }
+    bool operator!() const { return !m_ptr; }
+
+    bool operator==(const CFunctionPtr& other) const { return m_ptr == other.m_ptr; }
+    bool operator!=(const CFunctionPtr& other) const { return m_ptr != other.m_ptr; }
+
+private:
+    Ptr m_ptr { nullptr };
+};
+
+
 // FunctionPtr:
 //
 // FunctionPtr should be used to wrap pointers to C/C++ functions in JSC
index 1baed1d..465b890 100644 (file)
@@ -9414,18 +9414,18 @@ void SpeculativeJIT::compileCallDOM(Node* node)
     JSValueRegs resultRegs = result.regs();
 
     flushRegisters();
-    DOMJIT::FunctionWithoutTypeCheck function = signature->functionWithoutTypeCheck;
-    assertIsTaggedWith(function, CFunctionPtrTag);
+
+    auto function = CFunctionPtr(signature->functionWithoutTypeCheck);
     unsigned argumentCountIncludingThis = signature->argumentCount + 1;
     switch (argumentCountIncludingThis) {
     case 1:
-        callOperation(reinterpret_cast<J_JITOperation_EP>(function), extractResult(resultRegs), regs[0]);
+        callOperation(reinterpret_cast<J_JITOperation_EP>(function.get()), extractResult(resultRegs), regs[0]);
         break;
     case 2:
-        callOperation(reinterpret_cast<J_JITOperation_EPP>(function), extractResult(resultRegs), regs[0], regs[1]);
+        callOperation(reinterpret_cast<J_JITOperation_EPP>(function.get()), extractResult(resultRegs), regs[0], regs[1]);
         break;
     case 3:
-        callOperation(reinterpret_cast<J_JITOperation_EPPP>(function), extractResult(resultRegs), regs[0], regs[1], regs[2]);
+        callOperation(reinterpret_cast<J_JITOperation_EPPP>(function.get()), extractResult(resultRegs), regs[0], regs[1], regs[2]);
         break;
     default:
         RELEASE_ASSERT_NOT_REACHED();
index 0493732..e825bb9 100644 (file)
@@ -37,13 +37,13 @@ namespace JSC { namespace DOMJIT {
 #define JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS 2
 #define JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS_INCLUDING_THIS (1 + JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS)
 
-using FunctionWithoutTypeCheck = void (*)();
+using FunctionPtr = void (*WTF_VTBL_FUNCPTR_PTRAUTH(DOMJITFunctionPtrTag))();
 
 class Signature {
 public:
     template<typename... Arguments>
-    constexpr Signature(FunctionWithoutTypeCheck functionWithoutTypeCheck, const ClassInfo* classInfo, Effect effect, SpeculatedType result, Arguments... arguments)
-        : functionWithoutTypeCheck(functionWithoutTypeCheck)
+    constexpr Signature(CFunctionPtr functionWithoutTypeCheck, const ClassInfo* classInfo, Effect effect, SpeculatedType result, Arguments... arguments)
+        : functionWithoutTypeCheck(functionWithoutTypeCheck.get())
         , classInfo(classInfo)
         , result(result)
         , arguments {static_cast<SpeculatedType>(arguments)...}
@@ -52,7 +52,7 @@ public:
     {
     }
 
-    FunctionWithoutTypeCheck functionWithoutTypeCheck;
+    const FunctionPtr functionWithoutTypeCheck;
     const ClassInfo* const classInfo;
     const SpeculatedType result;
     const SpeculatedType arguments[JSC_DOMJIT_SIGNATURE_MAX_ARGUMENTS];
index ac1adbb..af1ba4b 100644 (file)
@@ -12580,17 +12580,16 @@ private:
 
         unsigned argumentCountIncludingThis = signature->argumentCount + 1;
         LValue result;
-        DOMJIT::FunctionWithoutTypeCheck function = signature->functionWithoutTypeCheck;
-        assertIsTaggedWith(function, CFunctionPtrTag);
+        auto function = CFunctionPtr(signature->functionWithoutTypeCheck);
         switch (argumentCountIncludingThis) {
         case 1:
-            result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EP>(function)), m_callFrame, operands[0]);
+            result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EP>(function.get())), m_callFrame, operands[0]);
             break;
         case 2:
-            result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EPP>(function)), m_callFrame, operands[0], operands[1]);
+            result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EPP>(function.get())), m_callFrame, operands[0], operands[1]);
             break;
         case 3:
-            result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EPPP>(function)), m_callFrame, operands[0], operands[1], operands[2]);
+            result = vmCall(Int64, m_out.operation(reinterpret_cast<J_JITOperation_EPPP>(function.get())), m_callFrame, operands[0], operands[1], operands[2]);
             break;
         default:
             RELEASE_ASSERT_NOT_REACHED();
index 5e341bd..42525a0 100644 (file)
 #include "CallFrame.h"
 #include "ConstructData.h"
 #include "JSCast.h"
-
-#if CPU(ARM64E)
-#include <ptrauth.h>
-#endif
+#include <wtf/PtrTag.h>
 
 namespace WTF {
 class PrintStream;
@@ -41,100 +38,96 @@ class JSArrayBufferView;
 class Snippet;
 struct HashTable;
 
-#if CPU(ARM64E)
-#define WTF_METHOD_TABLE_ENTRY(method) \
-    __ptrauth(ptrauth_key_process_independent_code, true, ptrauth_string_discriminator("MethodTable." #method)) method
-#else
-#define WTF_METHOD_TABLE_ENTRY(method) method
-#endif
+#define METHOD_TABLE_ENTRY(method) \
+    WTF_VTBL_FUNCPTR_PTRAUTH_STR("MethodTable." #method) method
 
 struct MethodTable {
     using DestroyFunctionPtr = void (*)(JSCell*);
-    DestroyFunctionPtr WTF_METHOD_TABLE_ENTRY(destroy);
+    DestroyFunctionPtr METHOD_TABLE_ENTRY(destroy);
 
     using VisitChildrenFunctionPtr = void (*)(JSCell*, SlotVisitor&);
-    VisitChildrenFunctionPtr WTF_METHOD_TABLE_ENTRY(visitChildren);
+    VisitChildrenFunctionPtr METHOD_TABLE_ENTRY(visitChildren);
 
     using GetCallDataFunctionPtr = CallType (*)(JSCell*, CallData&);
-    GetCallDataFunctionPtr WTF_METHOD_TABLE_ENTRY(getCallData);
+    GetCallDataFunctionPtr METHOD_TABLE_ENTRY(getCallData);
 
     using GetConstructDataFunctionPtr = ConstructType (*)(JSCell*, ConstructData&);
-    GetConstructDataFunctionPtr WTF_METHOD_TABLE_ENTRY(getConstructData);
+    GetConstructDataFunctionPtr METHOD_TABLE_ENTRY(getConstructData);
 
     using PutFunctionPtr = bool (*)(JSCell*, ExecState*, PropertyName propertyName, JSValue, PutPropertySlot&);
-    PutFunctionPtr WTF_METHOD_TABLE_ENTRY(put);
+    PutFunctionPtr METHOD_TABLE_ENTRY(put);
 
     using PutByIndexFunctionPtr = bool (*)(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
-    PutByIndexFunctionPtr WTF_METHOD_TABLE_ENTRY(putByIndex);
+    PutByIndexFunctionPtr METHOD_TABLE_ENTRY(putByIndex);
 
     using DeletePropertyFunctionPtr = bool (*)(JSCell*, ExecState*, PropertyName);
-    DeletePropertyFunctionPtr WTF_METHOD_TABLE_ENTRY(deleteProperty);
+    DeletePropertyFunctionPtr METHOD_TABLE_ENTRY(deleteProperty);
 
     using DeletePropertyByIndexFunctionPtr = bool (*)(JSCell*, ExecState*, unsigned);
-    DeletePropertyByIndexFunctionPtr WTF_METHOD_TABLE_ENTRY(deletePropertyByIndex);
+    DeletePropertyByIndexFunctionPtr METHOD_TABLE_ENTRY(deletePropertyByIndex);
 
     using GetOwnPropertySlotFunctionPtr = bool (*)(JSObject*, ExecState*, PropertyName, PropertySlot&);
-    GetOwnPropertySlotFunctionPtr WTF_METHOD_TABLE_ENTRY(getOwnPropertySlot);
+    GetOwnPropertySlotFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertySlot);
 
     using GetOwnPropertySlotByIndexFunctionPtr = bool (*)(JSObject*, ExecState*, unsigned, PropertySlot&);
-    GetOwnPropertySlotByIndexFunctionPtr WTF_METHOD_TABLE_ENTRY(getOwnPropertySlotByIndex);
+    GetOwnPropertySlotByIndexFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertySlotByIndex);
 
     using ToThisFunctionPtr = JSValue (*)(JSCell*, ExecState*, ECMAMode);
-    ToThisFunctionPtr WTF_METHOD_TABLE_ENTRY(toThis);
+    ToThisFunctionPtr METHOD_TABLE_ENTRY(toThis);
 
     using DefaultValueFunctionPtr = JSValue (*)(const JSObject*, ExecState*, PreferredPrimitiveType);
-    DefaultValueFunctionPtr WTF_METHOD_TABLE_ENTRY(defaultValue);
+    DefaultValueFunctionPtr METHOD_TABLE_ENTRY(defaultValue);
 
     using GetOwnPropertyNamesFunctionPtr = void (*)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
-    GetOwnPropertyNamesFunctionPtr WTF_METHOD_TABLE_ENTRY(getOwnPropertyNames);
+    GetOwnPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnPropertyNames);
 
     using GetOwnNonIndexPropertyNamesFunctionPtr = void (*)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
-    GetOwnNonIndexPropertyNamesFunctionPtr WTF_METHOD_TABLE_ENTRY(getOwnNonIndexPropertyNames);
+    GetOwnNonIndexPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getOwnNonIndexPropertyNames);
 
     using GetPropertyNamesFunctionPtr = void (*)(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
-    GetPropertyNamesFunctionPtr WTF_METHOD_TABLE_ENTRY(getPropertyNames);
+    GetPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getPropertyNames);
 
     using GetEnumerableLengthFunctionPtr = uint32_t (*)(ExecState*, JSObject*);
-    GetEnumerableLengthFunctionPtr WTF_METHOD_TABLE_ENTRY(getEnumerableLength);
+    GetEnumerableLengthFunctionPtr METHOD_TABLE_ENTRY(getEnumerableLength);
 
-    GetPropertyNamesFunctionPtr WTF_METHOD_TABLE_ENTRY(getStructurePropertyNames);
-    GetPropertyNamesFunctionPtr WTF_METHOD_TABLE_ENTRY(getGenericPropertyNames);
+    GetPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getStructurePropertyNames);
+    GetPropertyNamesFunctionPtr METHOD_TABLE_ENTRY(getGenericPropertyNames);
 
     using ClassNameFunctionPtr = String (*)(const JSObject*, VM&);
-    ClassNameFunctionPtr WTF_METHOD_TABLE_ENTRY(className);
+    ClassNameFunctionPtr METHOD_TABLE_ENTRY(className);
 
     using ToStringNameFunctionPtr = String (*)(const JSObject*, ExecState*);
-    ToStringNameFunctionPtr WTF_METHOD_TABLE_ENTRY(toStringName);
+    ToStringNameFunctionPtr METHOD_TABLE_ENTRY(toStringName);
 
     using CustomHasInstanceFunctionPtr = bool (*)(JSObject*, ExecState*, JSValue);
-    CustomHasInstanceFunctionPtr WTF_METHOD_TABLE_ENTRY(customHasInstance);
+    CustomHasInstanceFunctionPtr METHOD_TABLE_ENTRY(customHasInstance);
 
     using DefineOwnPropertyFunctionPtr = bool (*)(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, bool);
-    DefineOwnPropertyFunctionPtr WTF_METHOD_TABLE_ENTRY(defineOwnProperty);
+    DefineOwnPropertyFunctionPtr METHOD_TABLE_ENTRY(defineOwnProperty);
 
     using PreventExtensionsFunctionPtr = bool (*)(JSObject*, ExecState*);
-    PreventExtensionsFunctionPtr WTF_METHOD_TABLE_ENTRY(preventExtensions);
+    PreventExtensionsFunctionPtr METHOD_TABLE_ENTRY(preventExtensions);
 
     using IsExtensibleFunctionPtr = bool (*)(JSObject*, ExecState*);
-    IsExtensibleFunctionPtr WTF_METHOD_TABLE_ENTRY(isExtensible);
+    IsExtensibleFunctionPtr METHOD_TABLE_ENTRY(isExtensible);
 
     using SetPrototypeFunctionPtr = bool (*)(JSObject*, ExecState*, JSValue, bool shouldThrowIfCantSet);
-    SetPrototypeFunctionPtr WTF_METHOD_TABLE_ENTRY(setPrototype);
+    SetPrototypeFunctionPtr METHOD_TABLE_ENTRY(setPrototype);
 
     using GetPrototypeFunctionPtr = JSValue (*)(JSObject*, ExecState*);
-    GetPrototypeFunctionPtr WTF_METHOD_TABLE_ENTRY(getPrototype);
+    GetPrototypeFunctionPtr METHOD_TABLE_ENTRY(getPrototype);
 
     using DumpToStreamFunctionPtr = void (*)(const JSCell*, PrintStream&);
-    DumpToStreamFunctionPtr WTF_METHOD_TABLE_ENTRY(dumpToStream);
+    DumpToStreamFunctionPtr METHOD_TABLE_ENTRY(dumpToStream);
 
     using HeapSnapshotFunctionPtr = void (*)(JSCell*, HeapSnapshotBuilder&);
-    HeapSnapshotFunctionPtr WTF_METHOD_TABLE_ENTRY(heapSnapshot);
+    HeapSnapshotFunctionPtr METHOD_TABLE_ENTRY(heapSnapshot);
 
     using EstimatedSizeFunctionPtr = size_t (*)(JSCell*, VM&);
-    EstimatedSizeFunctionPtr WTF_METHOD_TABLE_ENTRY(estimatedSize);
+    EstimatedSizeFunctionPtr METHOD_TABLE_ENTRY(estimatedSize);
 
     using VisitOutputConstraintsPtr = void (*)(JSCell*, SlotVisitor&);
-    VisitOutputConstraintsPtr WTF_METHOD_TABLE_ENTRY(visitOutputConstraints);
+    VisitOutputConstraintsPtr METHOD_TABLE_ENTRY(visitOutputConstraints);
 };
 
 #define CREATE_MEMBER_CHECKER(member) \
index 8f353c0..0901e84 100644 (file)
@@ -36,6 +36,7 @@ using PtrTag = WTF::PtrTag;
     v(B3CompilationPtrTag) \
     v(BytecodePtrTag) \
     v(CopyFunctionPtrTag) \
+    v(DOMJITFunctionPtrTag) \
     v(DisassemblyPtrTag) \
     v(ExceptionHandlerPtrTag) \
     v(ExecutableMemoryPtrTag) \
index b898881..5e9f8d1 100644 (file)
@@ -827,7 +827,7 @@ private:
     void finishCreation(VM&, JSGlobalObject*);
 };
 
-static const DOMJIT::Signature DOMJITFunctionObjectSignature((DOMJIT::FunctionWithoutTypeCheck)DOMJITFunctionObject::functionWithoutTypeCheck, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
+static const DOMJIT::Signature DOMJITFunctionObjectSignature(DOMJITFunctionObject::functionWithoutTypeCheck, DOMJITFunctionObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
 
 void DOMJITFunctionObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
 {
@@ -881,7 +881,7 @@ private:
     void finishCreation(VM&, JSGlobalObject*);
 };
 
-static const DOMJIT::Signature DOMJITCheckSubClassObjectSignature((DOMJIT::FunctionWithoutTypeCheck)DOMJITCheckSubClassObject::functionWithoutTypeCheck, DOMJITCheckSubClassObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
+static const DOMJIT::Signature DOMJITCheckSubClassObjectSignature(DOMJITCheckSubClassObject::functionWithoutTypeCheck, DOMJITCheckSubClassObject::info(), DOMJIT::Effect::forRead(DOMJIT::HeapRange::top()), SpecInt32Only);
 
 void DOMJITCheckSubClassObject::finishCreation(VM& vm, JSGlobalObject* globalObject)
 {
index d7068df..3365a22 100644 (file)
@@ -1,3 +1,15 @@
+2019-08-02  Mark Lam  <mark.lam@apple.com>
+
+        [ARM64E] Harden the diversity of the DOMJIT::Signature::unsafeFunction pointer.
+        https://bugs.webkit.org/show_bug.cgi?id=200292
+        <rdar://problem/53706881>
+
+        Reviewed by Geoffrey Garen.
+
+        * wtf/PtrTag.h:
+        - Introducing WTF_VTBL_FUNCPTR_PTRAUTH and WTF_VTBL_FUNCPTR_PTRAUTH_STR macros for
+          defining vtbl function pointer style pointer signing modifier.
+
 2019-08-02  Eric Carlson  <eric.carlson@apple.com>
 
         uniqueLogIdentifier() should generate a 64-bit identifier
index 14349bd..4366463 100644 (file)
@@ -422,6 +422,14 @@ void assertIsNullOrTaggedWith(PtrType ptr, PtrTag tag)
 
 inline bool usesPointerTagging() { return true; }
 
+// vtbl function pointers need to sign with ptrauth_key_process_independent_code
+// because they reside in library code shared by multiple processes.
+// The second argument to __ptrauth() being 1 means to use the address of the pointer
+// for diversification as well. __ptrauth() expects a literal int for this argument.
+#define WTF_VTBL_FUNCPTR_PTRAUTH(discriminator) WTF_VTBL_FUNCPTR_PTRAUTH_STR(#discriminator)
+#define WTF_VTBL_FUNCPTR_PTRAUTH_STR(discriminatorStr) \
+    __ptrauth(ptrauth_key_process_independent_code, 1, ptrauth_string_discriminator(discriminatorStr))
+
 #else // not CPU(ARM64E)
 
 inline void registerPtrTagLookup(PtrTagLookup*) { }
@@ -546,6 +554,9 @@ template<typename PtrType> void assertIsNullOrTaggedWith(PtrType, PtrTag) { }
 
 inline bool usesPointerTagging() { return false; }
 
+#define WTF_VTBL_FUNCPTR_PTRAUTH(discriminator)
+#define WTF_VTBL_FUNCPTR_PTRAUTH_STR(discriminatorStr)
+
 #endif // CPU(ARM64E)
 
 } // namespace WTF
index f9f8c5f..7e83bfa 100644 (file)
@@ -1,3 +1,18 @@
+2019-08-02  Mark Lam  <mark.lam@apple.com>
+
+        [ARM64E] Harden the diversity of the DOMJIT::Signature::unsafeFunction pointer.
+        https://bugs.webkit.org/show_bug.cgi?id=200292
+        <rdar://problem/53706881>
+
+        Reviewed by Geoffrey Garen.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateImplementation):
+        - Update to work with the new DOMJIT::Signature constructor.
+
+        * bindings/scripts/test/JS/JSTestDOMJIT.cpp:
+        - Re-base test results.
+
 2019-08-02  Keith Rollin  <krollin@apple.com>
 
         Consistently use Obj-C boolean literals
index 33f4e69..4341717 100644 (file)
@@ -4009,7 +4009,7 @@ sub GenerateImplementation
             my $domJITSignatureName = "DOMJITSignatureFor" . $interface->type->name . $codeGenerator->WK_ucfirst($operation->name);
             my $classInfo = "JS" . $interface->type->name . "::info()";
             my $resultType = GetResultTypeFilter($interface, $operation->type);
-            my $domJITSignatureHeader = "static const JSC::DOMJIT::Signature ${domJITSignatureName}((JSC::DOMJIT::FunctionWithoutTypeCheck)${nameOfFunctionWithoutTypeCheck},";
+            my $domJITSignatureHeader = "static const JSC::DOMJIT::Signature ${domJITSignatureName}(${nameOfFunctionWithoutTypeCheck},";
             my $domJITSignatureFooter = "$classInfo, JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), ${resultType}";
             foreach my $argument (@{$operation->arguments}) {
                 my $type = $argument->type;
index 7f3aabb..2b6d9b2 100644 (file)
@@ -105,15 +105,15 @@ JSC::EncodedJSValue jsTestDOMJITByteStringNullableAttr(JSC::ExecState*, JSC::Enc
 JSC::EncodedJSValue jsTestDOMJITUsvStringNullableAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
 JSC::EncodedJSValue jsTestDOMJITNodeNullableAttr(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
 
-static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITGetAttribute((JSC::DOMJIT::FunctionWithoutTypeCheck)jsTestDOMJITPrototypeFunctionGetAttributeWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLNullable<IDLDOMString>>::value, DOMJIT::IDLArgumentTypeFilter<IDLDOMString>::value);
+static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITGetAttribute(jsTestDOMJITPrototypeFunctionGetAttributeWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLNullable<IDLDOMString>>::value, DOMJIT::IDLArgumentTypeFilter<IDLDOMString>::value);
 
-static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITItem((JSC::DOMJIT::FunctionWithoutTypeCheck)jsTestDOMJITPrototypeFunctionItemWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLDOMString>::value, DOMJIT::IDLArgumentTypeFilter<IDLUnsignedShort>::value, DOMJIT::IDLArgumentTypeFilter<IDLUnsignedShort>::value);
+static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITItem(jsTestDOMJITPrototypeFunctionItemWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLDOMString>::value, DOMJIT::IDLArgumentTypeFilter<IDLUnsignedShort>::value, DOMJIT::IDLArgumentTypeFilter<IDLUnsignedShort>::value);
 
-static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITHasAttribute((JSC::DOMJIT::FunctionWithoutTypeCheck)jsTestDOMJITPrototypeFunctionHasAttributeWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLBoolean>::value);
+static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITHasAttribute(jsTestDOMJITPrototypeFunctionHasAttributeWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLBoolean>::value);
 
-static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITGetElementById((JSC::DOMJIT::FunctionWithoutTypeCheck)jsTestDOMJITPrototypeFunctionGetElementByIdWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLInterface<Element>>::value, DOMJIT::IDLArgumentTypeFilter<IDLRequiresExistingAtomStringAdaptor<IDLDOMString>>::value);
+static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITGetElementById(jsTestDOMJITPrototypeFunctionGetElementByIdWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLInterface<Element>>::value, DOMJIT::IDLArgumentTypeFilter<IDLRequiresExistingAtomStringAdaptor<IDLDOMString>>::value);
 
-static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITGetElementsByName((JSC::DOMJIT::FunctionWithoutTypeCheck)jsTestDOMJITPrototypeFunctionGetElementsByNameWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLInterface<NodeList>>::value, DOMJIT::IDLArgumentTypeFilter<IDLAtomStringAdaptor<IDLDOMString>>::value);
+static const JSC::DOMJIT::Signature DOMJITSignatureForTestDOMJITGetElementsByName(jsTestDOMJITPrototypeFunctionGetElementsByNameWithoutTypeCheck, JSTestDOMJIT::info(), JSC::DOMJIT::Effect::forRead(DOMJIT::AbstractHeapRepository::DOM), DOMJIT::IDLResultTypeFilter<IDLInterface<NodeList>>::value, DOMJIT::IDLArgumentTypeFilter<IDLAtomStringAdaptor<IDLDOMString>>::value);
 
 static const JSC::DOMJIT::GetterSetter DOMJITAttributeForTestDOMJITAnyAttr {
     jsTestDOMJITAnyAttr,