Commit cbc89a24 authored by David Major's avatar David Major
Browse files

Bug 932100 - Part 2: Move DLL blocklist code to mozglue. r=bsmedberg, r=glandium, a=bajaj

--HG--
rename : toolkit/xre/nsWindowsDllBlocklist.cpp => mozglue/build/WindowsDllBlocklist.cpp
parent 01441498
Loading
Loading
Loading
Loading
+5 −10
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#endif

#include "mozilla/Telemetry.h"
#include "mozilla/WindowsDllBlocklist.h"

static void Output(const char *fmt, ... )
{
@@ -92,9 +93,6 @@ public:
XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_CreateAppDataType XRE_CreateAppData;
XRE_FreeAppDataType XRE_FreeAppData;
#ifdef XRE_HAS_DLL_BLOCKLIST
XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
#endif
XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
XRE_mainType XRE_main;

@@ -102,9 +100,6 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
    { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
    { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
    { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
#ifdef XRE_HAS_DLL_BLOCKLIST
    { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
#endif
    { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
    { "XRE_main", (NSFuncPtr*) &XRE_main },
    { nullptr, nullptr }
@@ -210,6 +205,10 @@ int main(int argc, char* argv[])
  gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
#endif

#ifdef HAS_DLL_BLOCKLIST
  DllBlocklist_Initialize();
#endif

  // We do this because of data in bug 771745
  XPCOMGlueEnablePreload();

@@ -227,10 +226,6 @@ int main(int argc, char* argv[])
    return 255;
  }

#ifdef XRE_HAS_DLL_BLOCKLIST
  XRE_SetupDllBlocklist();
#endif

  if (gotCounters) {
#if defined(XP_WIN)
    XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
+12 −10
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL

#include "mozilla/Telemetry.h"
#include "mozilla/WindowsDllBlocklist.h"

using namespace mozilla;

@@ -154,9 +155,6 @@ static void AttachToTestHarness()
XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_CreateAppDataType XRE_CreateAppData;
XRE_FreeAppDataType XRE_FreeAppData;
#ifdef XRE_HAS_DLL_BLOCKLIST
XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
#endif
XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
XRE_mainType XRE_main;
@@ -166,9 +164,6 @@ static const nsDynamicFunctionLoad kXULFuncs[] = {
    { "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
    { "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
    { "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
#ifdef XRE_HAS_DLL_BLOCKLIST
    { "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
#endif
    { "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
    { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
    { "XRE_main", (NSFuncPtr*) &XRE_main },
@@ -607,6 +602,17 @@ int main(int argc, char* argv[])

  nsIFile *xreDirectory;

#ifdef HAS_DLL_BLOCKLIST
  DllBlocklist_Initialize();

  // In order to be effective against AppInit DLLs, the blocklist must be
  // initialized before user32.dll is loaded into the process. If this assert
  // ever fires, then the fix for bug 932100 has been defeated and the
  // blocklist will miss AppInit DLLs. You should use a delayload or reorder
  // the code to prevent user32.dll from loading during early startup.
  MOZ_ASSERT(!GetModuleHandleA("user32.dll"));
#endif

  nsresult rv = InitXPCOMGlue(argv[0], &xreDirectory);
  if (NS_FAILED(rv)) {
    return 255;
@@ -614,10 +620,6 @@ int main(int argc, char* argv[])

  XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);

#ifdef XRE_HAS_DLL_BLOCKLIST
  XRE_SetupDllBlocklist();
#endif

  if (gotCounters) {
#if defined(XP_WIN)
    XRE_TelemetryAccumulate(mozilla::Telemetry::EARLY_GLUESTARTUP_READ_OPS,
+3 −2
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@
#include <stdio.h>

#include "mozilla/Util.h"
#include "mozilla/WindowsDllBlocklist.h"

#include "nsXULAppAPI.h"
#ifdef XP_MACOSX
@@ -38,8 +39,8 @@ main(int argc, char** argv, char** envp)
    setbuf(stdout, 0);
#endif

#ifdef XRE_HAS_DLL_BLOCKLIST
    XRE_SetupDllBlocklist();
#ifdef HAS_DLL_BLOCKLIST
    DllBlocklist_Initialize();
#endif

    int result = XRE_XPCShellMain(argc, argv, envp);
+8 −1
Original line number Diff line number Diff line
@@ -47,7 +47,14 @@ ifneq (,$(filter -DEFAULTLIB:mozcrt,$(MOZ_GLUE_LDFLAGS)))
NO_INSTALL_IMPORT_LIBRARY = 1
endif

EXTRA_DSO_LDOPTS += $(MOZ_ZLIB_LIBS)

EXTRA_DSO_LDOPTS += \
	$(MOZ_ZLIB_LIBS) \
	version.lib \
	$(NULL)

STL_FLAGS=

endif

ifeq (Darwin_1,$(OS_TARGET)_$(MOZ_REPLACE_MALLOC))
+84 −26
Original line number Diff line number Diff line
@@ -5,18 +5,15 @@

#include <windows.h>
#include <winternl.h>
#include <io.h>

#include <stdio.h>
#include <string.h>

#pragma warning( push )
#pragma warning( disable : 4275 4530 ) // See msvc-stl-wrapper.template.h
#include <map>
#pragma warning( pop )

#include "nsXULAppAPI.h"

#define MOZ_NO_MOZALLOC
#include "nsAutoPtr.h"
#include "nsThreadUtils.h"

#include "prlog.h"

#include "nsWindowsDllInterceptor.h"
#include "mozilla/WindowsVersion.h"
@@ -24,10 +21,6 @@

using namespace mozilla;

#ifdef MOZ_CRASHREPORTER
#include "nsExceptionHandler.h"
#endif

#define ALL_VERSIONS   ((unsigned long long)-1LL)

// DLLs sometimes ship without a version number, particularly early
@@ -153,7 +146,47 @@ static DllBlockInfo sWindowsDllBlocklist[] = {
// define this for very verbose dll load debug spew
#undef DEBUG_very_verbose

extern bool gInXPCOMLoadOnMainThread;
static const char kBlockedDllsParameter[] = "BlockedDllList=";
static const int kBlockedDllsParameterLen =
  sizeof(kBlockedDllsParameter) - 1;

static const char kBlocklistInitFailedParameter[] = "BlocklistInitFailed=";
static const int kBlocklistInitFailedParameterLen =
  sizeof(kBlocklistInitFailedParameter) - 1;

static const char kUser32BeforeBlocklistParameter[] = "User32BeforeBlocklist=";
static const int kUser32BeforeBlocklistParameterLen =
  sizeof(kUser32BeforeBlocklistParameterLen) - 1;

static DWORD sThreadLoadingXPCOMModule;
static bool sBlocklistInitFailed;
static bool sUser32BeforeBlocklist;

// Duplicated from xpcom glue. Ideally this should be shared.
static void
printf_stderr(const char *fmt, ...)
{
  if (IsDebuggerPresent()) {
    char buf[2048];
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    buf[sizeof(buf) - 1] = '\0';
    va_end(args);
    OutputDebugStringA(buf);
  }

  FILE *fp = _fdopen(_dup(2), "a");
  if (!fp)
      return;

  va_list args;
  va_start(args, fmt);
  vfprintf(fp, fmt, args);
  va_end(args);

  fclose(fp);
}

namespace {

@@ -170,7 +203,7 @@ struct RVAMap {
    DWORD alignedOffset = (offset / info.dwAllocationGranularity) *
                          info.dwAllocationGranularity;

    NS_ASSERTION(offset - alignedOffset < info.dwAllocationGranularity, "Wtf");
    MOZ_ASSERT(offset - alignedOffset < info.dwAllocationGranularity, "Wtf");

    mRealView = ::MapViewOfFile(map, FILE_MAP_READ, 0, alignedOffset,
                                sizeof(T) + (offset - alignedOffset));
@@ -544,7 +577,7 @@ continue_loading:
  printf_stderr("LdrLoadDll: continuing load... ('%S')\n", moduleFileName->Buffer);
#endif

  if (gInXPCOMLoadOnMainThread && NS_IsMainThread()) {
  if (GetCurrentThreadId() == sThreadLoadingXPCOMModule) {
    // Check to ensure that the DLL has ASLR.
    full_fname = getFullPath(filePath, fname);
    if (!full_fname) {
@@ -566,31 +599,56 @@ WindowsDllInterceptor NtDllIntercept;

} // anonymous namespace

void
XRE_SetupDllBlocklist()
NS_EXPORT void
DllBlocklist_Initialize()
{
  if (GetModuleHandleA("user32.dll")) {
    sUser32BeforeBlocklist = true;
  }

  NtDllIntercept.Init("ntdll.dll");

  ReentrancySentinel::InitializeStatics();

  bool ok = NtDllIntercept.AddHook("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);

  if (!ok) {
    sBlocklistInitFailed = true;
#ifdef DEBUG
  if (!ok)
    printf_stderr ("LdrLoadDll hook failed, no dll blocklisting active\n");
#endif
  }
}

#ifdef MOZ_CRASHREPORTER
  if (!ok) {
    CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("DllBlockList Failed\n"));
NS_EXPORT void
DllBlocklist_SetInXPCOMLoadOnMainThread(bool inXPCOMLoadOnMainThread)
{
  if (inXPCOMLoadOnMainThread) {
    MOZ_ASSERT(sThreadLoadingXPCOMModule == 0, "Only one thread should be doing this");
    sThreadLoadingXPCOMModule = GetCurrentThreadId();
  } else {
    sThreadLoadingXPCOMModule = 0;
  }
#endif
}

#ifdef MOZ_CRASHREPORTER
void
CrashReporter::WriteBlockedDlls(HANDLE file)
NS_EXPORT void
DllBlocklist_WriteNotes(HANDLE file)
{
  DWORD nBytes;

  WriteFile(file, kBlockedDllsParameter, kBlockedDllsParameterLen, &nBytes, nullptr);
  DllBlockSet::Write(file);
  WriteFile(file, "\n", 1, &nBytes, nullptr);

  if (sBlocklistInitFailed) {
    WriteFile(file, kBlocklistInitFailedParameter,
              kBlocklistInitFailedParameterLen, &nBytes, nullptr);
    WriteFile(file, "1\n", 2, &nBytes, nullptr);
  }

  if (sUser32BeforeBlocklist) {
    WriteFile(file, kUser32BeforeBlocklistParameter,
              kUser32BeforeBlocklistParameterLen, &nBytes, nullptr);
    WriteFile(file, "1\n", 2, &nBytes, nullptr);
  }
}
#endif
Loading