Bug 286382 - Don't load DLLs from the current directory; r=vlad
authorEhsan Akhgari <ehsan@mozilla.com>
Tue, 29 Jun 2010 20:15:11 -0400
changeset 48843 767706ccb547952b3555063b3b487a97d9f30b6c
parent 48842 caec0c83740f1785c8e0f05c58a5fae32ab770eb
child 48844 6a75787301c453bbb52263b6eede86eb1c2271bf
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs286382
milestone2.0b4pre
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 286382 - Don't load DLLs from the current directory; r=vlad
toolkit/library/nsDllMain.cpp
toolkit/xre/nsWindowsDllBlocklist.cpp
toolkit/xre/nsWindowsWMain.cpp
--- a/toolkit/library/nsDllMain.cpp
+++ b/toolkit/library/nsDllMain.cpp
@@ -35,32 +35,39 @@
  * 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 <windows.h>
 #include "nsToolkit.h"
 
+#ifdef MOZ_ENABLE_LIBXUL
+#include "../xre/nsWindowsDllBlocklist.cpp"
+#endif
+
 #if defined(__GNUC__)
 // If DllMain gets name mangled, it won't be seen.
 extern "C" {
 #endif
 
 BOOL APIENTRY DllMain(  
 #ifdef WINCE
                       HANDLE hModule, 
 #else 
                       HINSTANCE hModule, 
 #endif
                       DWORD reason, 
                       LPVOID lpReserved )
 {
     switch( reason ) {
         case DLL_PROCESS_ATTACH:
+#ifdef MOZ_ENABLE_LIBXUL
+            SetupDllBlocklist();
+#endif
             nsToolkit::Startup((HINSTANCE)hModule);
             break;
 
         case DLL_THREAD_ATTACH:
             break;
     
         case DLL_THREAD_DETACH:
             break;
--- a/toolkit/xre/nsWindowsDllBlocklist.cpp
+++ b/toolkit/xre/nsWindowsDllBlocklist.cpp
@@ -35,16 +35,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include <windows.h>
 #include <winternl.h>
 
 #include <stdio.h>
+#include <string.h>
 
 #include "nsAutoPtr.h"
 
 #include "prlog.h"
 
 #include "nsWindowsDllInterceptor.h"
 
 #define IN_WINDOWS_DLL_BLOCKLIST
@@ -52,16 +53,41 @@
 
 #ifndef STATUS_DLL_NOT_FOUND
 #define STATUS_DLL_NOT_FOUND ((DWORD)0xC0000135L)
 #endif
 
 // define this for very verbose dll load debug spew
 #undef DEBUG_very_verbose
 
+// This class takes care of setting and restoring the current directory
+// to make sure that the process current directory is not searched when
+// loading DLLs.
+class CurrentDirectoryGuard {
+public:
+  CurrentDirectoryGuard() {
+    ::GetCurrentDirectoryW(MAX_PATH, mCwd);
+
+    WCHAR appPath[MAX_PATH] = {L'\0'};
+    ::GetModuleFileNameW(NULL, appPath, MAX_PATH);
+    LPWSTR lastBackslash = wcsrchr(appPath, L'\\');
+    if (lastBackslash) {
+      *lastBackslash = L'\0';
+    }
+    ::SetCurrentDirectoryW(appPath);
+  }
+
+  ~CurrentDirectoryGuard() {
+    ::SetCurrentDirectoryW(mCwd);
+  }
+
+private:
+  WCHAR mCwd[MAX_PATH];
+};
+
 // The signature for LdrLoadDll changed at some point, with the second arg
 // becoming a PULONG instead of a ULONG.  This should only matter on 64-bit
 // systems, for which there was no support earlier -- on 32-bit systems,
 // they should be the same size.
 PR_STATIC_ASSERT(sizeof(PULONG) == sizeof(ULONG));
 
 typedef NTSTATUS (NTAPI *LdrLoadDll_func) (PWCHAR filePath, PULONG flags, PUNICODE_STRING moduleFileName, PHANDLE handle);
 
@@ -204,16 +230,24 @@ patched_LdrLoadDll (PWCHAR filePath, PUL
 
 continue_loading:
 #ifdef DEBUG_very_verbose
   printf_stderr("LdrLoadDll: continuing load... ('%S')\n", moduleFileName->Buffer);
 #endif
 
   NS_SetHasLoadedNewDLLs();
 
+  // We need to make sure that the OS implementation of LdrLoadDll does not attempt
+  // to load any DLLs from the current working directory.  That's almost never what
+  // we want, and it can cause us load unexpected DLLs.  This guard protects against
+  // that by setting the current directory to the application's directory before
+  // LdrLoadDll is called, and restoring it to the original value when that call
+  // returns.
+  CurrentDirectoryGuard cwdGuard;
+
   return stub_LdrLoadDll(filePath, flags, moduleFileName, handle);
 }
 
 WindowsDllInterceptor NtDllIntercept;
 
 void
 SetupDllBlocklist()
 {
--- a/toolkit/xre/nsWindowsWMain.cpp
+++ b/toolkit/xre/nsWindowsWMain.cpp
@@ -3,17 +3,18 @@
 // narrow-character strings.
 
 #ifndef XP_WIN
 #error This file only makes sense on Windows.
 #endif
 
 #include "nsUTF8Utils.h"
 
-#if defined(_MSC_VER) && defined(_M_IX86) && defined(XRE_WANT_DLL_BLOCKLIST)
+#if defined(_MSC_VER) && defined(_M_IX86) && defined(XRE_WANT_DLL_BLOCKLIST) \
+   !defined(MOZ_ENABLE_LIBXUL)
 #include "nsWindowsDllBlocklist.cpp"
 #else
 #undef XRE_WANT_DLL_BLOCKLIST
 #endif
 
 
 #ifdef __MINGW32__