Fix ReadMemory AV.
authorMike McLaughlin <mikem@microsoft.com>
Wed, 30 Mar 2016 01:06:25 +0000 (18:06 -0700)
committerMike McLaughlin <mikem@microsoft.com>
Wed, 30 Mar 2016 01:09:08 +0000 (18:09 -0700)
Use simple probing to validate read/write memory with a try/catch and explicit h/w exception holder.

Put probing in separate noinline and optnone function for optimized builds.

Fix assert in exception code mapping in context.cpp by handling SIGSEGV subcode SI_KERNEL.

src/debug/shared/dbgtransportsession.cpp
src/pal/src/thread/context.cpp

index b6efe7cc2d9c7028858d0f3362e3b973f0695a1e..e3827735d560cb59ac25d21eb480a2e691ce1a2d 100644 (file)
@@ -1126,6 +1126,34 @@ DbgTransportSession::Message * DbgTransportSession::RemoveMessageFromSendQueue(D
 #endif
 
 #ifndef RIGHT_SIDE_COMPILE
+
+#ifdef FEATURE_PAL
+__attribute__((noinline))
+__attribute__((optnone))
+static void 
+ProbeMemory(__in_ecount(cbBuffer) volatile PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess)
+{
+    // Need an throw in this function to fool the C++ runtime into handling the 
+    // possible h/w exception below.
+    if (pbBuffer == NULL)
+    {
+        throw PAL_SEHException();
+    }
+
+    // Simple one byte at a time probing
+    while (cbBuffer > 0)
+    {
+        volatile BYTE read = *pbBuffer;
+        if (fWriteAccess)
+        {
+            *pbBuffer = read;
+        }
+        ++pbBuffer;
+        --cbBuffer;
+    }
+}
+#endif // FEATURE_PAL
+
 // Check read and optionally write memory access to the specified range of bytes. Used to check
 // ReadProcessMemory and WriteProcessMemory requests.
 HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuffer, DWORD cbBuffer, bool fWriteAccess)
@@ -1138,7 +1166,6 @@ HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuf
 
     // VirtualQuery doesn't know much about memory allocated outside of PAL's VirtualAlloc 
     // that's why on Unix we can't rely on in to detect invalid memory reads  
-    // TODO: We need to find and use appropriate memory map API on other operating systems. 
 #ifndef FEATURE_PAL
     do 
     {
@@ -1179,11 +1206,24 @@ HRESULT DbgTransportSession::CheckBufferAccess(__in_ecount(cbBuffer) PBYTE pbBuf
         }
     }
     while (cbBuffer > 0);
+#else
+    try
+    {
+        // Need to explicit h/w exception holder so to catch them in ProbeMemory
+        CatchHardwareExceptionHolder __catchHardwareException;
+
+        ProbeMemory(pbBuffer, cbBuffer, fWriteAccess);
+    }
+    catch(...)
+    {
+        return HRESULT_FROM_WIN32(ERROR_INVALID_ADDRESS);
+    }
 #endif
 
     // The specified region has passed all of our checks.
     return S_OK;
 }
+
 #endif // !RIGHT_SIDE_COMPILE
 
 // Initialize all session state to correct starting values. Used during Init() and on the LS when we
index ed2790a8e639b124b506ec1a8f5dfc0450b60787..6958961be0d508d79bb8262800f173954cf3cd3a 100644 (file)
@@ -655,7 +655,7 @@ DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo,
                             return exceptionCode;
                         }
                     }
-                    // fall through
+                    return EXCEPTION_ACCESS_VIOLATION;
                 }
 #endif
                 default: