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 415330 13863e08584ae95ac1262b517bf8ef06dd29dbdf
parent 415329 b315cc407da4438cede0f2a88aeeb87a932cd325
child 415331 6d8ebb6476c98519589404ab0793afc969c49216
push id102554
push useraklotz@mozilla.com
push dateTue, 24 Apr 2018 18:50:30 +0000
treeherdermozilla-inbound@13863e08584a [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