Title: [288885] trunk/Source
Revision
288885
Author
[email protected]
Date
2022-02-01 09:33:58 -0800 (Tue, 01 Feb 2022)

Log Message

Enhance sanitizeStackForVM() to assist with crash analysis.
https://bugs.webkit.org/show_bug.cgi?id=235752
rdar://81014601

Reviewed by Michael Saboff.

Source/_javascript_Core:

1. Remove the AssemblyHelpers version of sanitizeStack.  Instead, make the 3
   JIT operation functions call sanitizeStackForVM() instead.  This ensures
   that sanitizeStack crashes are not obscured as generic JIT crashes.

2. Add sanity check RELEASE_ASSERTs to VM::setLastStackTop() with a capture of
   the relevant variables for crash analysis.

3. Fix logSanitizeStack() so that it no longer relies on vm.topCallFrame.
   vm.topCallFrame may not be properly initialized at all the places that
   sanitizeStackForVM() is called.

4. Add a JSLock check to sanitizeStackForVM(), and return early if not owned by
   the current thread.  If the JSLock is not owned by the current thread, we can't
   rely on vm.lastStackTop() being a sane value.  Hence, it's not possible to
   do stack sanitization correctly.

   Add sanity check RELEASE_ASSERTs to sanitizeStackForVM() with a capture of
   the relevant variables for crash analysis.

* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::sanitizeStackInline): Deleted.
* jit/AssemblyHelpers.h:
* jit/JITOperations.cpp:
(JSC::JSC_DEFINE_JIT_OPERATION):
* jit/ThunkGenerators.cpp:
(JSC::slowPathFor):
* runtime/JSLock.cpp:
(JSC::JSLock::didAcquireLock):
(JSC::JSLock::grabAllLocks):
* runtime/VM.cpp:
(JSC::VM::VM):
(JSC::VM::setLastStackTop):
(JSC::logSanitizeStack):
(JSC::sanitizeStackForVM):
* runtime/VM.h:

Source/WTF:

* wtf/Threading.h:
(WTF::Thread::savedStackPointerAtVMEntry const):
(WTF::Thread::savedLastStackTop const):
(WTF::Thread::savedStackPointerAtVMEntry): Deleted.
(WTF::Thread::savedLastStackTop): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (288884 => 288885)


--- trunk/Source/_javascript_Core/ChangeLog	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/ChangeLog	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,3 +1,47 @@
+2022-02-01  Mark Lam  <[email protected]>
+
+        Enhance sanitizeStackForVM() to assist with crash analysis.
+        https://bugs.webkit.org/show_bug.cgi?id=235752
+        rdar://81014601
+
+        Reviewed by Michael Saboff.
+
+        1. Remove the AssemblyHelpers version of sanitizeStack.  Instead, make the 3
+           JIT operation functions call sanitizeStackForVM() instead.  This ensures
+           that sanitizeStack crashes are not obscured as generic JIT crashes.
+
+        2. Add sanity check RELEASE_ASSERTs to VM::setLastStackTop() with a capture of
+           the relevant variables for crash analysis.
+
+        3. Fix logSanitizeStack() so that it no longer relies on vm.topCallFrame.
+           vm.topCallFrame may not be properly initialized at all the places that
+           sanitizeStackForVM() is called.
+
+        4. Add a JSLock check to sanitizeStackForVM(), and return early if not owned by
+           the current thread.  If the JSLock is not owned by the current thread, we can't
+           rely on vm.lastStackTop() being a sane value.  Hence, it's not possible to
+           do stack sanitization correctly.
+
+           Add sanity check RELEASE_ASSERTs to sanitizeStackForVM() with a capture of
+           the relevant variables for crash analysis.
+
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::sanitizeStackInline): Deleted.
+        * jit/AssemblyHelpers.h:
+        * jit/JITOperations.cpp:
+        (JSC::JSC_DEFINE_JIT_OPERATION):
+        * jit/ThunkGenerators.cpp:
+        (JSC::slowPathFor):
+        * runtime/JSLock.cpp:
+        (JSC::JSLock::didAcquireLock):
+        (JSC::JSLock::grabAllLocks):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        (JSC::VM::setLastStackTop):
+        (JSC::logSanitizeStack):
+        (JSC::sanitizeStackForVM):
+        * runtime/VM.h:
+
 2022-01-31  Yusuke Suzuki  <[email protected]>
 
         Revert OSAllocator behavior to pre-Structure-Allocator change one

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp (288884 => 288885)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.cpp	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1113,19 +1113,6 @@
 #endif
 }
 
-void AssemblyHelpers::sanitizeStackInline(VM& vm, GPRReg scratch)
-{
-    loadPtr(vm.addressOfLastStackTop(), scratch);
-    Jump done = branchPtr(BelowOrEqual, stackPointerRegister, scratch);
-    Label loop = label();
-    storePtr(TrustedImmPtr(nullptr), Address(scratch));
-    addPtr(TrustedImmPtr(sizeof(void*)), scratch);
-    branchPtr(Above, stackPointerRegister, scratch).linkTo(loop, this);
-    done.link(this);
-    move(stackPointerRegister, scratch);
-    storePtr(scratch, vm.addressOfLastStackTop());
-}
-
 void AssemblyHelpers::cageWithoutUntagging(Gigacage::Kind kind, GPRReg storage)
 {
 #if GIGACAGE_ENABLED

Modified: trunk/Source/_javascript_Core/jit/AssemblyHelpers.h (288884 => 288885)


--- trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/jit/AssemblyHelpers.h	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2011-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1710,8 +1710,6 @@
         return branchTest8(Zero, AbsoluteAddress(vm.heap.addressOfMutatorShouldBeFenced()));
     }
     
-    void sanitizeStackInline(VM&, GPRReg scratch);
-    
     // Emits the branch structure for typeof. The code emitted by this doesn't fall through. The
     // functor is called at those points where we have pinpointed a type. One way to use this is to
     // have the functor emit the code to put the type string into an appropriate register and then

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (288884 => 288885)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -1448,11 +1448,13 @@
 
 JSC_DEFINE_JIT_OPERATION(operationLinkCall, SlowPathReturnType, (CallFrame* calleeFrame, JSGlobalObject* globalObject, CallLinkInfo* callLinkInfo))
 {
+    sanitizeStackForVM(globalObject->vm());
     return linkFor(calleeFrame, globalObject, callLinkInfo);
 }
 
 JSC_DEFINE_JIT_OPERATION(operationLinkPolymorphicCall, SlowPathReturnType, (CallFrame* calleeFrame, JSGlobalObject* globalObject, CallLinkInfo* callLinkInfo))
 {
+    sanitizeStackForVM(globalObject->vm());
     ASSERT(callLinkInfo->specializationKind() == CodeForCall);
     JSCell* calleeAsFunctionCell;
     SlowPathReturnType result = virtualForWithFunction(globalObject, calleeFrame, callLinkInfo, calleeAsFunctionCell);
@@ -1464,6 +1466,7 @@
 
 JSC_DEFINE_JIT_OPERATION(operationVirtualCall, SlowPathReturnType, (CallFrame* calleeFrame, JSGlobalObject* globalObject, CallLinkInfo* callLinkInfo))
 {
+    sanitizeStackForVM(globalObject->vm());
     JSCell* calleeAsFunctionCellIgnored;
     return virtualForWithFunction(globalObject, calleeFrame, callLinkInfo, calleeAsFunctionCellIgnored);
 }

Modified: trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp (288884 => 288885)


--- trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/jit/ThunkGenerators.cpp	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2010-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -192,7 +192,6 @@
 
 static void slowPathFor(CCallHelpers& jit, VM& vm, Sprt_JITOperation_EGCli slowPathFunction)
 {
-    jit.sanitizeStackInline(vm, GPRInfo::nonArgGPR0);
     jit.emitFunctionPrologue();
     jit.storePtr(GPRInfo::callFrameRegister, &vm.topCallFrame);
 #if OS(WINDOWS) && CPU(X86_64)

Modified: trunk/Source/_javascript_Core/runtime/JSLock.cpp (288884 => 288885)


--- trunk/Source/_javascript_Core/runtime/JSLock.cpp	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/runtime/JSLock.cpp	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2005-2022 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -138,8 +138,7 @@
     m_entryAtomStringTable = thread.setCurrentAtomStringTable(m_vm->atomStringTable());
     ASSERT(m_entryAtomStringTable);
 
-    m_vm->setLastStackTop(thread.savedLastStackTop());
-    ASSERT(thread.stack().contains(m_vm->lastStackTop()));
+    m_vm->setLastStackTop(thread);
 
     if (m_vm->heap.hasAccess())
         m_shouldReleaseHeapAccess = false;
@@ -277,7 +276,7 @@
 
     Thread& thread = Thread::current();
     m_vm->setStackPointerAtVMEntry(thread.savedStackPointerAtVMEntry());
-    m_vm->setLastStackTop(thread.savedLastStackTop());
+    m_vm->setLastStackTop(thread);
 }
 
 JSLock::DropAllLocks::DropAllLocks(VM* vm)

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (288884 => 288885)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -242,9 +242,8 @@
         CRASH_WITH_INFO(0x4242424220202020, 0xbadbeef0badbeef, 0x1234123412341234, 0x1337133713371337);
 
     interpreter = new Interpreter(*this);
-    StackBounds stack = Thread::current().stack();
     updateSoftReservedZoneSize(Options::softReservedZoneSize());
-    setLastStackTop(stack.origin());
+    setLastStackTop(Thread::current());
 
     JSRunLoopTimer::Manager::shared().registerVM(*this);
 
@@ -503,9 +502,11 @@
     m_needToFirePrimitiveGigacageEnabled = true;
 }
 
-void VM::setLastStackTop(void* lastStackTop)
-{ 
-    m_lastStackTop = lastStackTop;
+void VM::setLastStackTop(const Thread& thread)
+{
+    m_lastStackTop = thread.savedLastStackTop();
+    auto& stack = thread.stack();
+    RELEASE_ASSERT(stack.contains(m_lastStackTop), 0x5510, m_lastStackTop, stack.origin(), stack.end());
 }
 
 Ref<VM> VM::createContextGroup(HeapType heapType)
@@ -1050,16 +1051,11 @@
     m_checkpointSideState.shrinkToFit();
 }
 
-void logSanitizeStack(VM& vm)
+static void logSanitizeStack(VM& vm)
 {
-    if (Options::verboseSanitizeStack() && vm.topCallFrame) {
-        int dummy;
+    if (UNLIKELY(Options::verboseSanitizeStack())) {
         auto& stackBounds = Thread::current().stack();
-        dataLog(
-            "Sanitizing stack for VM = ", RawPointer(&vm), " with top call frame at ", RawPointer(vm.topCallFrame),
-            ", current stack pointer at ", RawPointer(&dummy), ", in ",
-            pointerDump(vm.topCallFrame->codeBlock()), ", last code origin = ",
-            vm.topCallFrame->codeOrigin(), ", last stack top = ", RawPointer(vm.lastStackTop()), ", in stack range [", RawPointer(stackBounds.origin()), ", ", RawPointer(stackBounds.end()), "]\n");
+        dataLogLn("Sanitizing stack for VM = ", RawPointer(&vm), ", current stack pointer at ", RawPointer(currentStackPointer()), ", last stack top = ", RawPointer(vm.lastStackTop()), ", in stack range (", RawPointer(stackBounds.end()), ", ", RawPointer(stackBounds.origin()), "]");
     }
 }
 
@@ -1270,17 +1266,20 @@
 
 void sanitizeStackForVM(VM& vm)
 {
+    auto& thread = Thread::current();
+    auto& stack = thread.stack();
+    if (!vm.currentThreadIsHoldingAPILock())
+        return; // vm.lastStackTop() may not be set up correctly if JSLock is not held.
+
     logSanitizeStack(vm);
-    if (vm.topCallFrame) {
-        auto& stackBounds = Thread::current().stack();
-        ASSERT(vm.currentThreadIsHoldingAPILock());
-        ASSERT_UNUSED(stackBounds, stackBounds.contains(vm.lastStackTop()));
-    }
+
+    RELEASE_ASSERT(stack.contains(vm.lastStackTop()), 0xaa10, vm.lastStackTop(), stack.origin(), stack.end());
 #if ENABLE(C_LOOP)
     vm.interpreter->cloopStack().sanitizeStack();
 #else
     sanitizeStackForVMImpl(&vm);
 #endif
+    RELEASE_ASSERT(stack.contains(vm.lastStackTop()), 0xaa20, vm.lastStackTop(), stack.origin(), stack.end());
 }
 
 size_t VM::committedStackByteCount()

Modified: trunk/Source/_javascript_Core/runtime/VM.h (288884 => 288885)


--- trunk/Source/_javascript_Core/runtime/VM.h	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008-2021 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -774,7 +774,7 @@
 
     void** addressOfLastStackTop() { return &m_lastStackTop; }
     void* lastStackTop() { return m_lastStackTop; }
-    void setLastStackTop(void*);
+    void setLastStackTop(const Thread&);
     
     void firePrimitiveGigacageEnabledIfNecessary()
     {
@@ -1162,6 +1162,5 @@
 #endif
 
 JS_EXPORT_PRIVATE void sanitizeStackForVM(VM&);
-void logSanitizeStack(VM&);
 
 } // namespace JSC

Modified: trunk/Source/WTF/ChangeLog (288884 => 288885)


--- trunk/Source/WTF/ChangeLog	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/WTF/ChangeLog	2022-02-01 17:33:58 UTC (rev 288885)
@@ -1,3 +1,17 @@
+2022-02-01  Mark Lam  <[email protected]>
+
+        Enhance sanitizeStackForVM() to assist with crash analysis.
+        https://bugs.webkit.org/show_bug.cgi?id=235752
+        rdar://81014601
+
+        Reviewed by Michael Saboff.
+
+        * wtf/Threading.h:
+        (WTF::Thread::savedStackPointerAtVMEntry const):
+        (WTF::Thread::savedLastStackTop const):
+        (WTF::Thread::savedStackPointerAtVMEntry): Deleted.
+        (WTF::Thread::savedLastStackTop): Deleted.
+
 2022-01-31  Yusuke Suzuki  <[email protected]>
 
         Revert OSAllocator behavior to pre-Structure-Allocator change one

Modified: trunk/Source/WTF/wtf/Threading.h (288884 => 288885)


--- trunk/Source/WTF/wtf/Threading.h	2022-02-01 17:18:59 UTC (rev 288884)
+++ trunk/Source/WTF/wtf/Threading.h	2022-02-01 17:33:58 UTC (rev 288885)
@@ -231,7 +231,7 @@
     }
 #endif
 
-    void* savedStackPointerAtVMEntry()
+    void* savedStackPointerAtVMEntry() const
     {
         return m_savedStackPointerAtVMEntry;
     }
@@ -241,7 +241,7 @@
         m_savedStackPointerAtVMEntry = stackPointerAtVMEntry;
     }
 
-    void* savedLastStackTop()
+    void* savedLastStackTop() const
     {
         return m_savedLastStackTop;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to