diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp index f8cbf7933824..d547e45a180e 100644 --- a/browser/app/nsBrowserApp.cpp +++ b/browser/app/nsBrowserApp.cpp @@ -54,8 +54,6 @@ #include "nsStringGlue.h" #ifdef XP_WIN -// we want to use the DLL blocklist if possible -#define XRE_WANT_DLL_BLOCKLIST // we want a wmain entry point #include "nsWindowsWMain.cpp" #endif diff --git a/toolkit/xre/nsWindowsDllBlocklist.cpp b/toolkit/xre/nsWindowsDllBlocklist.cpp deleted file mode 100644 index e64ed2ce4bb5..000000000000 --- a/toolkit/xre/nsWindowsDllBlocklist.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Corp - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Vladimir Vukicevic - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include -#include - -#include - -#include "nsAutoPtr.h" - -#include "prlog.h" - -#include "nsWindowsDllInterceptor.h" - -#define IN_WINDOWS_DLL_BLOCKLIST -#include "nsWindowsDllBlocklist.h" - -typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle); - -static LdrLoadDll_func stub_LdrLoadDll = 0; - -static NTSTATUS NTAPI -patched_LdrLoadDll (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle) -{ - // We have UCS2 (UTF16?), we want ASCII, but we also just want the filename portion -#define DLLNAME_MAX 128 - char dllName[DLLNAME_MAX+1]; - - // Dirty secret about this UNICODE_STRING: it's not guaranteed to be - // null-terminated, and Length is supposed to contain the number of - // characters. But in the UNICODE_STRING passed to this function, - // that doesn't seem to be true -- Length is often much bigger than - // the actual valid characters of the string, which seems to always - // be null terminated. So, we take the minimum of len or the length - // to the first null byte, if any, but we still can't assume the null - // termination. - int len = moduleFileName->Length; - wchar_t *fn_buf = moduleFileName->Buffer; - - int count = 0; - while (count < len && fn_buf[count] != 0) - count++; - - len = count; - - // copy it into fname, which will then be guaranteed null-terminated - nsAutoArrayPtr fname = new wchar_t[len+1]; - wcsncpy(fname, moduleFileName->Buffer, len); - - wchar_t *dll_part = wcsrchr(fname, L'\\'); - if (dll_part) { - dll_part = dll_part + 1; - len = (fname+len) - dll_part; - } else { - dll_part = fname; - } - - // if it's too long, then, we assume we won't want to block it, - // since DLLNAME_MAX should be at least long enough to hold the longest - // entry in our blocklist. - if (len > DLLNAME_MAX) - goto continue_loading; - - // copy over to our char byte buffer, lowercasing ASCII as we go - for (int i = 0; i < len; i++) { - wchar_t c = dll_part[i]; - if (c >= 'A' && c <= 'Z') - c += 'a' - 'A'; - - if (c > 0x7f) { - // welp, it's not ascii; if we need to add non-ascii things to - // our blocklist, we'll have to remove this limitation. - goto continue_loading; - } - - dllName[i] = (char) c; - } - - dllName[len] = 0; - - // then compare to everything on the blocklist - DllBlockInfo *info = &sWindowsDllBlocklist[0]; - while (info->name) { - if (strcmp(info->name, dllName) == 0) - break; - - info++; - } - - if (info->name) { - BOOL load_ok = FALSE; - - if (info->maxVersion != ALL_VERSIONS) { - // figure out the length of the string that we need - DWORD pathlen = SearchPathW(filePath, fname, L".dll", 0, NULL, NULL); - if (pathlen == 0) { - // uh, we couldn't find the DLL at all, so... - return STATUS_DLL_NOT_FOUND; - } - - nsAutoArrayPtr full_fname = new wchar_t[pathlen+1]; - - // now actually grab it - SearchPathW(filePath, fname, L".dll", pathlen+1, full_fname, NULL); - - DWORD zero; - DWORD infoSize = GetFileVersionInfoSizeW(full_fname, &zero); - - // If we failed to get the version information, we block. - - if (infoSize != 0) { - nsAutoArrayPtr infoData = new unsigned char[infoSize]; - VS_FIXEDFILEINFO *vInfo; - UINT vInfoLen; - - if (GetFileVersionInfoW(full_fname, 0, infoSize, infoData) && - VerQueryValueW(infoData, L"\\", (LPVOID*) &vInfo, &vInfoLen)) - { - unsigned long long fVersion = - ((unsigned long long)vInfo->dwFileVersionMS) << 32 | - ((unsigned long long)vInfo->dwFileVersionLS); - - // finally do the version check, and if it's greater than our block - // version, keep loading - if (fVersion > info->maxVersion) - goto continue_loading; - } - } - } - - PR_LogPrint("LdrLoadDll: Blocking load of '%s'", dllName); - return STATUS_DLL_NOT_FOUND; - } - -continue_loading: - return stub_LdrLoadDll(filePath, flags, moduleFileName, handle); -} - -WindowsDllInterceptor NtDllIntercept; - -void -SetupDllBlocklist() -{ - NtDllIntercept.Init("ntdll.dll"); - - bool ok = NtDllIntercept.AddHook("LdrLoadDll", patched_LdrLoadDll, (void**) &stub_LdrLoadDll); - - if (!ok) - PR_LogPrint ("LdrLoadDll hook failed, no dll blocklisting active"); -} - - - - diff --git a/toolkit/xre/nsWindowsDllBlocklist.h b/toolkit/xre/nsWindowsDllBlocklist.h deleted file mode 100644 index 149cc7980dc9..000000000000 --- a/toolkit/xre/nsWindowsDllBlocklist.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Corp - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Vladimir Vukicevic - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef IN_WINDOWS_DLL_BLOCKLIST -#error This file should only be included by nsWindowsDllBlocklist.cpp -#endif - -#define ALL_VERSIONS ((unsigned long long)-1LL) - -struct DllBlockInfo { - // The name of the DLL -- in LOWERCASE! It will be compared to - // a lowercase version of the DLL name only. - const char *name; - - // If maxVersion is ALL_VERSIONS, we'll block all versions of this - // dll. Otherwise, we'll block all versions less than or equal to - // the given version, as queried by GetFileVersionInfo and - // VS_FIXEDFILEINFO's dwFileVersionMS and dwFileVersionLS fields. - // - // Note that the version is usually 4 components, which is A.B.C.D - // encoded as 0x AAAA BBBB CCCC DDDD ULL (spaces added for clarity), - // but it's not required to be of that format. - unsigned long long maxVersion; -}; - -static DllBlockInfo sWindowsDllBlocklist[] = { - // EXAMPLE: - // { "uxtheme.dll", ALL_VERSIONS }, - // { "uxtheme.dll", 0x0000123400000000ULL }, - // The DLL name must be in lowercase! - { NULL, 0 } -}; diff --git a/toolkit/xre/nsWindowsDllInterceptor.h b/toolkit/xre/nsWindowsDllInterceptor.h deleted file mode 100644 index 65e7f9356795..000000000000 --- a/toolkit/xre/nsWindowsDllInterceptor.h +++ /dev/null @@ -1,228 +0,0 @@ -/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Mozilla Corp - * Portions created by the Initial Developer are Copyright (C) 2009 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Vladimir Vukicevic - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef NS_WINDOWS_DLL_INTERCEPTOR_H_ -#define NS_WINDOWS_DLL_INTERCEPTOR_H_ -#include -#include - -/* - * Simple trampoline interception - * - * 1. Save first N bytes of OrigFunction to trampoline, where N is a - * number of bytes >= 5 that are instruction aligned. - * - * 2. Replace first 5 bytes of OrigFunction with a jump to the Hook - * function. - * - * 3. After N bytes of the trampoline, add a jump to OrigFunction+N to - * continue original program flow. - * - * 4. Hook function needs to call the trampoline during its execution, - * to invoke the original function (so address of trampoline is - * returned). - * - */ - -class WindowsDllInterceptor -{ - typedef unsigned char *byteptr_t; -public: - WindowsDllInterceptor() - : mModule(0) - { - } - - WindowsDllInterceptor(const char *modulename, int nhooks = 0) { - Init(modulename, nhooks); - } - - void Init(const char *modulename, int nhooks = 0) { - if (mModule) - return; - - mModule = LoadLibraryEx(modulename, NULL, 0); - if (!mModule) { - //printf("LoadLibraryEx for '%s' failed\n", modulename); - return; - } - - int hooksPerPage = 4096 / kHookSize; - if (nhooks == 0) - nhooks = hooksPerPage; - - mMaxHooks = nhooks + (hooksPerPage % nhooks); - mCurHooks = 0; - - mHookPage = (byteptr_t) VirtualAllocEx(GetCurrentProcess(), NULL, mMaxHooks * kHookSize, - MEM_COMMIT | MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - - if (!mHookPage) { - mModule = 0; - return; - } - } - - void LockHooks() { - if (!mModule) - return; - - DWORD op; - VirtualProtectEx(GetCurrentProcess(), mHookPage, mMaxHooks * kHookSize, PAGE_EXECUTE_READ, &op); - - mModule = 0; - } - - bool AddHook(const char *pname, - void *hookDest, - void **origFunc) - { - if (!mModule) - return false; - - void *pAddr = (void *) GetProcAddress(mModule, pname); - if (!pAddr) { - //printf ("GetProcAddress failed\n"); - return false; - } - - void *tramp = CreateTrampoline(pAddr, hookDest); - if (!tramp) { - //printf ("CreateTrampoline failed\n"); - return false; - } - - *origFunc = tramp; - - return true; - } - -protected: - const static int kPageSize = 4096; - const static int kHookSize = 128; - - HMODULE mModule; - byteptr_t mHookPage; - int mMaxHooks; - int mCurHooks; - - byteptr_t CreateTrampoline(void *origFunction, - void *dest) - { - byteptr_t tramp = FindTrampolineSpace(); - if (!tramp) - return 0; - - byteptr_t origBytes = (byteptr_t) origFunction; - - int nBytes = 0; - while (nBytes < 5) { - // Understand some simple instructions that might be found in a - // prologue; we might need to extend this as necessary. - // - // Note! If we ever need to understand jump instructions, we'll - // need to rewrite the displacement argument. - if (origBytes[nBytes] >= 0x88 && origBytes[nBytes] <= 0x8B) { - // various MOVs; but only handle the case where it truly is a 2-byte instruction - unsigned char b = origBytes[nBytes+1]; - if (((b & 0xc0) == 0xc0) || - (((b & 0xc0) == 0x00) && - ((b & 0x38) != 0x20) && ((b & 0x38) != 0x28))) - { - nBytes += 2; - } else { - // complex MOV, bail - return 0; - } - } else if (origBytes[nBytes] == 0x68) { - // PUSH with 4-byte operand - nBytes += 5; - } else if ((origBytes[nBytes] & 0xf0) == 0x50) { - // 1-byte PUSH/POP - nBytes++; - } else { - //printf ("Unknown x86 instruction byte 0x%02x, aborting trampoline\n", origBytes[nBytes]); - return 0; - } - } - - if (nBytes > 100) { - //printf ("Too big!"); - return 0; - } - - memcpy(tramp, origFunction, nBytes); - - // OrigFunction+N, the target of the trampoline - byteptr_t trampDest = origBytes + nBytes; - - tramp[nBytes] = 0xE9; // jmp - *((intptr_t*)(tramp+nBytes+1)) = (intptr_t)trampDest - (intptr_t)(tramp+nBytes+5); // target displacement - - // ensure we can modify the original code - DWORD op; - if (!VirtualProtectEx(GetCurrentProcess(), origFunction, nBytes, PAGE_EXECUTE_READWRITE, &op)) { - //printf ("VirtualProtectEx failed! %d\n", GetLastError()); - return 0; - } - - // now modify the original bytes - origBytes[0] = 0xE9; // jmp - *((intptr_t*)(origBytes+1)) = (intptr_t)dest - (intptr_t)(origBytes+5); // target displacement - - // restore protection; if this fails we can't really do anything about it - VirtualProtectEx(GetCurrentProcess(), origFunction, nBytes, op, &op); - - return tramp; - } - - byteptr_t FindTrampolineSpace() { - if (mCurHooks >= mMaxHooks) - return 0; - - byteptr_t p = mHookPage + mCurHooks*kHookSize; - - mCurHooks++; - - return p; - } -}; - - -#endif /* NS_WINDOWS_DLL_INTERCEPTOR_H_ */ diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp index 7f81c22580df..0179e0ffbd7b 100644 --- a/toolkit/xre/nsWindowsWMain.cpp +++ b/toolkit/xre/nsWindowsWMain.cpp @@ -8,13 +8,6 @@ #include "nsUTF8Utils.h" -#if defined(_MSC_VER) && defined(_M_IX86) && defined(XRE_WANT_DLL_BLOCKLIST) -#include "nsWindowsDllBlocklist.cpp" -#else -#undef XRE_WANT_DLL_BLOCKLIST -#endif - - #ifdef __MINGW32__ /* MingW currently does not implement a wide version of the @@ -88,12 +81,9 @@ void ExtractEnvironmentFromCL(int &argc, char **&argv) } #endif + int wmain(int argc, WCHAR **argv) { -#ifdef XRE_WANT_DLL_BLOCKLIST - SetupDllBlocklist(); -#endif - char **argvConverted = new char*[argc + 1]; if (!argvConverted) return 127;