Bug 1314169: Move the WasmFaultHandler to last priority on Windows ASan builds. r=luke
authorDavid Major <dmajor@mozilla.com>
Mon, 14 Nov 2016 10:37:47 -0600
changeset 438644 888f093ce01504fb472d0646d29c08bcc5ef7b75
parent 438643 fb46a1dc34f92d6c8d9a2244edd73e2d394af5db
child 438645 e222819961af854aed85dfccc346b03e3de0d477
push id35794
push usersledru@mozilla.com
push dateMon, 14 Nov 2016 22:18:09 +0000
reviewersluke
bugs1314169
milestone52.0a1
Bug 1314169: Move the WasmFaultHandler to last priority on Windows ASan builds. r=luke Win64 ASan relies on a VectoredExceptionHandler to create shadow memory regions on demand. If WasmFaultHandler gets the exception first, it can itself fault while looking at shadow memory, leading to an infinite recursion. Unfortunately, due to an ordering problem, we also have to disable the MemoryProtectionExceptionHandler when we do this. MozReview-Commit-ID: aHwnBFI6dG
js/src/ds/MemoryProtectionExceptionHandler.cpp
js/src/wasm/WasmSignalHandlers.cpp
--- a/js/src/ds/MemoryProtectionExceptionHandler.cpp
+++ b/js/src/ds/MemoryProtectionExceptionHandler.cpp
@@ -90,18 +90,27 @@ class ProtectedRegionTree
 
 static bool sExceptionHandlerInstalled = false;
 
 static ProtectedRegionTree sProtectedRegions;
 
 bool
 MemoryProtectionExceptionHandler::isDisabled()
 {
-    // There isn't currently any reason to disable it.
+#if defined(XP_WIN) && defined(MOZ_ASAN)
+    // Under Windows ASan, WasmFaultHandler registers itself at 'last' priority
+    // in order to let ASan's ShadowExceptionHandler stay at 'first' priority.
+    // Unfortunately that results in spurious wasm faults passing through the
+    // MemoryProtectionExceptionHandler, which breaks its assumption that any
+    // faults it sees are fatal. Just disable this handler in that case, as the
+    // crash annotations provided here are not critical for ASan builds.
+    return true;
+#else
     return false;
+#endif
 }
 
 void
 MemoryProtectionExceptionHandler::addRegion(void* addr, size_t size)
 {
     if (sExceptionHandlerInstalled)
         sProtectedRegions.insert(uintptr_t(addr), size);
 }
--- a/js/src/wasm/WasmSignalHandlers.cpp
+++ b/js/src/wasm/WasmSignalHandlers.cpp
@@ -1335,17 +1335,28 @@ ProcessHasSignalHandlers()
     {
         MOZ_CRASH("contention for interrupt signal");
     }
 #endif // defined(XP_WIN)
 
     // Install a SIGSEGV handler to handle safely-out-of-bounds asm.js heap
     // access and/or unaligned accesses.
 # if defined(XP_WIN)
-    if (!AddVectoredExceptionHandler(/* FirstHandler = */ true, WasmFaultHandler))
+#  if defined(MOZ_ASAN)
+    // Under ASan we need to let the ASan runtime's ShadowExceptionHandler stay
+    // in the first handler position. This requires some coordination with
+    // MemoryProtectionExceptionHandler::isDisabled().
+    const bool firstHandler = false;
+#  else
+    // Otherwise, WasmFaultHandler needs to go first, so that we can recover
+    // from wasm faults and continue execution without triggering handlers
+    // such as MemoryProtectionExceptionHandler that assume we are crashing.
+    const bool firstHandler = true;
+#  endif
+    if (!AddVectoredExceptionHandler(firstHandler, WasmFaultHandler))
         return false;
 # elif defined(XP_DARWIN)
     // OSX handles seg faults via the Mach exception handler above, so don't
     // install WasmFaultHandler.
 # else
     // SA_NODEFER allows us to reenter the signal handler if we crash while
     // handling the signal, and fall through to the Breakpad handler by testing
     // handlingSegFault.