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

--HG--
rename : toolkit/xre/nsWindowsDllBlocklist.cpp => mozglue/build/WindowsDllBlocklist.cpp
This commit is contained in:
David Major 2013-11-12 08:31:32 -05:00
parent 0233f4ada7
commit 4a637bff20
12 changed files with 170 additions and 77 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -45,7 +45,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))

View File

@ -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"));
}
#endif
}
#ifdef MOZ_CRASHREPORTER
void
CrashReporter::WriteBlockedDlls(HANDLE file)
NS_EXPORT void
DllBlocklist_SetInXPCOMLoadOnMainThread(bool inXPCOMLoadOnMainThread)
{
DllBlockSet::Write(file);
if (inXPCOMLoadOnMainThread) {
MOZ_ASSERT(sThreadLoadingXPCOMModule == 0, "Only one thread should be doing this");
sThreadLoadingXPCOMModule = GetCurrentThreadId();
} else {
sThreadLoadingXPCOMModule = 0;
}
}
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

View File

@ -0,0 +1,38 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_windowsdllblocklist_h
#define mozilla_windowsdllblocklist_h
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
#include <windows.h>
#include "mozilla/GuardObjects.h"
#include "nscore.h"
#define HAS_DLL_BLOCKLIST
NS_IMPORT void DllBlocklist_Initialize();
NS_IMPORT void DllBlocklist_SetInXPCOMLoadOnMainThread(bool inXPCOMLoadOnMainThread);
NS_IMPORT void DllBlocklist_WriteNotes(HANDLE file);
class AutoSetXPCOMLoadOnMainThread
{
public:
AutoSetXPCOMLoadOnMainThread(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
DllBlocklist_SetInXPCOMLoadOnMainThread(true);
}
~AutoSetXPCOMLoadOnMainThread() {
DllBlocklist_SetInXPCOMLoadOnMainThread(false);
}
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
#endif // defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
#endif // mozilla_windowsdllblocklist_h

View File

@ -31,6 +31,11 @@ if CONFIG['OS_TARGET'] == 'Android':
'BionicGlue.cpp',
]
if CONFIG['OS_TARGET'] == 'WINNT':
SOURCES += [
'WindowsDllBlocklist.cpp',
]
if CONFIG['MOZ_NUWA_PROCESS']:
EXPORTS.ipc += [
'Nuwa.h',
@ -42,6 +47,7 @@ if CONFIG['MOZ_NUWA_PROCESS']:
EXPORTS.mozilla += [
'arm.h',
'SSE.h',
'WindowsDllBlocklist.h',
]
if CONFIG['CPU_ARCH'].startswith('x86'):

View File

@ -83,6 +83,7 @@ using mozilla::InjectCrashRunnable;
#include "mozilla/mozalloc_oom.h"
#include "mozilla/LateWriteChecks.h"
#include "mozilla/WindowsDllBlocklist.h"
#if defined(XP_MACOSX)
CFStringRef reporterClientAppID = CFSTR("org.mozilla.crashreporter");
@ -222,11 +223,6 @@ static const char kIsGarbageCollectingParameter[] = "IsGarbageCollecting=";
static const int kIsGarbageCollectingParameterLen =
sizeof(kIsGarbageCollectingParameter)-1;
#ifdef XP_WIN
static const char kBlockedDllsParameter[] = "BlockedDllList=";
static const int kBlockedDllsParameterLen = sizeof(kBlockedDllsParameter) - 1;
#endif
// this holds additional data sent via the API
static Mutex* crashReporterAPILock;
static Mutex* notesFieldLock;
@ -545,9 +541,10 @@ bool MinidumpCallback(
WriteFile(hFile, isGarbageCollecting ? "1" : "0", 1, &nBytes, nullptr);
WriteFile(hFile, "\n", 1, &nBytes, nullptr);
}
WriteFile(hFile, kBlockedDllsParameter, kBlockedDllsParameterLen, &nBytes, nullptr);
WriteBlockedDlls(hFile);
WriteFile(hFile, "\n", 1, &nBytes, nullptr);
#ifdef HAS_DLL_BLOCKLIST
DllBlocklist_WriteNotes(hFile);
#endif
// Try to get some information about memory.
MEMORYSTATUSEX statex;

View File

@ -44,11 +44,6 @@ nsresult AppendAppNotesToCrashReport(const nsACString& data);
nsresult SetGarbageCollecting(bool collecting);
#ifdef XP_WIN
// Implemented by the blocklist, this method writes the blocklist annotation
void WriteBlockedDlls(HANDLE file);
#endif
nsresult SetRestartArgs(int argc, char** argv);
nsresult SetupExtraData(nsIFile* aAppDataDirectory,
const nsACString& aBuildID);

View File

@ -24,7 +24,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
EXPORTS += ['nsWindowsDllInterceptor.h']
SOURCES += [
'nsNativeAppSupportWin.cpp',
'nsWindowsDllBlocklist.cpp',
]
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
EXPORTS += ['MacQuirks.h']

View File

@ -437,12 +437,6 @@ XRE_API(bool,
XRE_API(void,
XRE_InstallX11ErrorHandler, ())
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
#define XRE_HAS_DLL_BLOCKLIST
XRE_API(void,
XRE_SetupDllBlocklist, ())
#endif
XRE_API(void,
XRE_TelemetryAccumulate, (int aID, uint32_t aSample))

View File

@ -32,6 +32,7 @@
#include "nsTraceRefcntImpl.h"
#include "nsIFile.h"
#include "mozilla/WindowsDllBlocklist.h"
#ifdef XP_WIN
#include <windows.h>
@ -61,8 +62,6 @@ GetNativeModuleLoaderLog()
return sLog;
}
bool gInXPCOMLoadOnMainThread = false;
#define LOG(level, args) PR_LOG(GetNativeModuleLoaderLog(), level, args)
NS_IMPL_QUERY_INTERFACE1(nsNativeModuleLoader,
@ -140,10 +139,12 @@ nsNativeModuleLoader::LoadModule(FileLocation &aFile)
}
// We haven't loaded this module before
gInXPCOMLoadOnMainThread = true;
rv = file->Load(&data.library);
gInXPCOMLoadOnMainThread = false;
{
#ifdef HAS_DLL_BLOCKLIST
AutoSetXPCOMLoadOnMainThread guard;
#endif
rv = file->Load(&data.library);
}
if (NS_FAILED(rv)) {
char errorMsg[1024] = "<unknown; can't get error from NSPR>";