Bug 1456054: Verify that a redirected address is accessible and backed by an image; r=handyman
authorAaron Klotz <aklotz@mozilla.com>
Mon, 23 Apr 2018 15:07:54 -0600
changeset 471481 13863e08584ae95ac1262b517bf8ef06dd29dbdf
parent 471480 b315cc407da4438cede0f2a88aeeb87a932cd325
child 471482 6d8ebb6476c98519589404ab0793afc969c49216
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershandyman
bugs1456054
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1456054: Verify that a redirected address is accessible and backed by an image; r=handyman
mozglue/misc/interceptor/MMPolicies.h
mozglue/misc/interceptor/PatcherBase.h
--- a/mozglue/misc/interceptor/MMPolicies.h
+++ b/mozglue/misc/interceptor/MMPolicies.h
@@ -134,18 +134,18 @@ public:
   /**
    * @return true if the page that hosts aVAddress is accessible.
    */
   bool IsPageAccessible(void* aVAddress) const
   {
     MEMORY_BASIC_INFORMATION mbi;
     SIZE_T result = ::VirtualQuery(aVAddress, &mbi, sizeof(mbi));
 
-    return result && mbi.AllocationProtect && mbi.State == MEM_COMMIT &&
-           mbi.Protect != PAGE_NOACCESS;
+    return result && mbi.AllocationProtect && (mbi.Type & MEM_IMAGE) &&
+           mbi.State == MEM_COMMIT && mbi.Protect != PAGE_NOACCESS;
   }
 
   bool FlushInstructionCache() const
   {
     return !!::FlushInstructionCache(::GetCurrentProcess(), nullptr, 0);
   }
 
 protected:
--- a/mozglue/misc/interceptor/PatcherBase.h
+++ b/mozglue/misc/interceptor/PatcherBase.h
@@ -40,45 +40,57 @@ protected:
 
       for (int8_t i = 0; i < offset; i++) {
         if (origFn[2 + i] != 0x90) {
           // Bail out on insufficient nop space.
           return Move(origFn);
         }
       }
 
-      origFn += 2 + offset;
-      return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy, origFn.GetAddress());
+      uintptr_t abstarget = (origFn + 2 + offset).GetAddress();
+      return EnsureTargetIsAccessible(Move(origFn), abstarget);
     }
 
 #if defined(_M_IX86)
     // If function entry is jmp [disp32] such as used by kernel32,
     // we resolve redirected address from import table.
     if (origFn[0] == 0xff && origFn[1] == 0x25) {
-      return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy,
-        reinterpret_cast<const void*>((origFn + 2).template ChasePointer<uintptr_t*>()));
+      uintptr_t abstarget = (origFn + 2).template ChasePointer<uintptr_t*>();
+      return EnsureTargetIsAccessible(Move(origFn), abstarget);
     }
 #elif defined(_M_X64)
     // If function entry is jmp [disp32] such as used by kernel32,
     // we resolve redirected address from import table.
     if (origFn[0] == 0x48 && origFn[1] == 0xff && origFn[2] == 0x25) {
-      return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy,
-        reinterpret_cast<const void*>((origFn + 3).ChasePointerFromDisp()));
+      uintptr_t abstarget = (origFn + 3).ChasePointerFromDisp();
+      return EnsureTargetIsAccessible(Move(origFn), abstarget);
     }
 
     if (origFn[0] == 0xe9) {
       // require for TestDllInterceptor with --disable-optimize
       uintptr_t abstarget = (origFn + 1).ReadDisp32AsAbsolute();
-      return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy, abstarget);
+      return EnsureTargetIsAccessible(Move(origFn), abstarget);
     }
 #endif
 
     return Move(origFn);
   }
 
+private:
+  ReadOnlyTargetFunction<MMPolicyT>
+  EnsureTargetIsAccessible(ReadOnlyTargetFunction<MMPolicyT> aOrigFn,
+                           uintptr_t aRedirAddress)
+  {
+    if (!mVMPolicy.IsPageAccessible(reinterpret_cast<void*>(aRedirAddress))) {
+      return Move(aOrigFn);
+    }
+
+    return ReadOnlyTargetFunction<MMPolicyT>(mVMPolicy, aRedirAddress);
+  }
+
 protected:
   VMPolicy  mVMPolicy;
 };
 
 } // namespace interceptor
 } // namespace mozilla
 
 #endif // mozilla_interceptor_PatcherBase_h