xpcom/components/nsNativeComponentLoader.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5  * This Original Code has been modified by IBM Corporation.
     6  * Modifications made by IBM described herein are
     7  * Copyright (c) International Business Machines
     8  * Corporation, 2000
     9  *
    10  * Modifications to Mozilla code or documentation
    11  * identified per MPL Section 3.3
    12  *
    13  * Date             Modified by     Description of modification
    14  * 04/20/2000       IBM Corp.      Added PR_CALLBACK for Optlink use in OS2
    15  */
    17 /* Allow logging in the release build */
    18 #ifdef MOZ_LOGGING
    19 #define FORCE_PR_LOG
    20 #endif
    22 #include "nsNativeComponentLoader.h"
    24 #include "prlog.h"
    25 #include "prinit.h"
    26 #include "prerror.h"
    28 #include "nsComponentManager.h"
    29 #include "ManifestParser.h" // for LogMessage
    30 #include "nsCRTGlue.h"
    31 #include "nsThreadUtils.h"
    32 #include "nsTraceRefcnt.h"
    34 #include "nsIFile.h"
    35 #include "mozilla/WindowsDllBlocklist.h"
    37 #ifdef XP_WIN
    38 #include <windows.h>
    39 #endif
    41 #ifdef XP_MACOSX
    42 #include <signal.h>
    43 #endif
    45 #ifdef VMS
    46 #include <lib$routines.h>
    47 #include <ssdef.h>
    48 #endif
    50 #ifdef DEBUG
    51 #define IMPLEMENT_BREAK_AFTER_LOAD
    52 #endif
    54 using namespace mozilla;
    56 static PRLogModuleInfo *
    57 GetNativeModuleLoaderLog()
    58 {
    59     static PRLogModuleInfo *sLog;
    60     if (!sLog)
    61         sLog = PR_NewLogModule("nsNativeModuleLoader");
    62     return sLog;
    63 }
    65 #define LOG(level, args) PR_LOG(GetNativeModuleLoaderLog(), level, args)
    67 NS_IMPL_QUERY_INTERFACE(nsNativeModuleLoader,
    68                         mozilla::ModuleLoader)
    70 NS_IMPL_ADDREF_USING_AGGREGATOR(nsNativeModuleLoader,
    71                                 nsComponentManagerImpl::gComponentManager)
    72 NS_IMPL_RELEASE_USING_AGGREGATOR(nsNativeModuleLoader,
    73                                  nsComponentManagerImpl::gComponentManager)
    75 nsresult
    76 nsNativeModuleLoader::Init()
    77 {
    78     MOZ_ASSERT(NS_IsMainThread(), "Startup not on main thread?");
    79     LOG(PR_LOG_DEBUG, ("nsNativeModuleLoader::Init()"));
    80     return NS_OK;
    81 }
    83 class LoadModuleMainThreadRunnable : public nsRunnable
    84 {
    85 public:
    86     LoadModuleMainThreadRunnable(nsNativeModuleLoader* loader,
    87                                  FileLocation &file)
    88         : mLoader(loader)
    89         , mFile(file)
    90         , mResult(nullptr)
    91     { }
    93     NS_IMETHOD Run()
    94     {
    95         mResult = mLoader->LoadModule(mFile);
    96         return NS_OK;
    97     }
    99     nsRefPtr<nsNativeModuleLoader> mLoader;
   100     FileLocation mFile;
   101     const mozilla::Module* mResult;
   102 };
   104 const mozilla::Module*
   105 nsNativeModuleLoader::LoadModule(FileLocation &aFile)
   106 {
   107     if (aFile.IsZip()) {
   108         NS_ERROR("Binary components cannot be loaded from JARs");
   109         return nullptr;
   110     }
   111     nsCOMPtr<nsIFile> file = aFile.GetBaseFile();
   112     nsresult rv;
   114     if (!NS_IsMainThread()) {
   115         // If this call is off the main thread, synchronously proxy it
   116         // to the main thread.
   117         nsRefPtr<LoadModuleMainThreadRunnable> r = new LoadModuleMainThreadRunnable(this, aFile);
   118         NS_DispatchToMainThread(r, NS_DISPATCH_SYNC);
   119         return r->mResult;
   120     }
   122     nsCOMPtr<nsIHashable> hashedFile(do_QueryInterface(file));
   123     if (!hashedFile) {
   124         NS_ERROR("nsIFile is not nsIHashable");
   125         return nullptr;
   126     }
   128     nsAutoCString filePath;
   129     file->GetNativePath(filePath);
   131     NativeLoadData data;
   133     if (mLibraries.Get(hashedFile, &data)) {
   134         NS_ASSERTION(data.module, "Corrupt mLibraries hash");
   135         LOG(PR_LOG_DEBUG,
   136             ("nsNativeModuleLoader::LoadModule(\"%s\") - found in cache",
   137              filePath.get()));
   138         return data.module;
   139     }
   141     // We haven't loaded this module before
   142     {
   143 #ifdef HAS_DLL_BLOCKLIST
   144       AutoSetXPCOMLoadOnMainThread guard;
   145 #endif
   146       rv = file->Load(&data.library);
   147     }
   149     if (NS_FAILED(rv)) {
   150         char errorMsg[1024] = "<unknown; can't get error from NSPR>";
   152         if (PR_GetErrorTextLength() < (int) sizeof(errorMsg))
   153             PR_GetErrorText(errorMsg);
   155         LogMessage("Failed to load native module at path '%s': (%lx) %s",
   156                    filePath.get(), rv, errorMsg);
   158         return nullptr;
   159     }
   161 #ifdef IMPLEMENT_BREAK_AFTER_LOAD
   162     nsAutoCString leafName;
   163     file->GetNativeLeafName(leafName);
   165     char *env = getenv("XPCOM_BREAK_ON_LOAD");
   166     char *blist;
   167     if (env && *env && (blist = strdup(env))) {
   168         char *nextTok = blist;
   169         while (char *token = NS_strtok(":", &nextTok)) {
   170             if (leafName.Find(token, true) != kNotFound) {
   171                 NS_BREAK();
   172             }
   173         }
   175         free(blist);
   176     }
   177 #endif
   179     void *module = PR_FindSymbol(data.library, "NSModule");
   180     if (!module) {
   181         LogMessage("Native module at path '%s' doesn't export symbol `NSModule`.",
   182                    filePath.get());
   183         PR_UnloadLibrary(data.library);
   184         return nullptr;
   185     }
   187     data.module = *(mozilla::Module const *const *) module;
   188     if (mozilla::Module::kVersion != data.module->mVersion) {
   189         LogMessage("Native module at path '%s' is incompatible with this version of Firefox, has version %i, expected %i.",
   190                    filePath.get(), data.module->mVersion,
   191                    mozilla::Module::kVersion);
   192         PR_UnloadLibrary(data.library);
   193         return nullptr;
   194     }
   196     mLibraries.Put(hashedFile, data); // infallible
   197     return data.module;
   198 }
   200 PLDHashOperator
   201 nsNativeModuleLoader::ReleaserFunc(nsIHashable* aHashedFile,
   202                                    NativeLoadData& aLoadData, void*)
   203 {
   204     aLoadData.module = nullptr;
   205     return PL_DHASH_NEXT;
   206 }
   208 PLDHashOperator
   209 nsNativeModuleLoader::UnloaderFunc(nsIHashable* aHashedFile,
   210                                    NativeLoadData& aLoadData, void*)
   211 {
   212     if (PR_LOG_TEST(GetNativeModuleLoaderLog(), PR_LOG_DEBUG)) {
   213         nsCOMPtr<nsIFile> file(do_QueryInterface(aHashedFile));
   215         nsAutoCString filePath;
   216         file->GetNativePath(filePath);
   218         LOG(PR_LOG_DEBUG,
   219             ("nsNativeModuleLoader::UnloaderFunc(\"%s\")", filePath.get()));
   220     }
   222 #ifdef NS_BUILD_REFCNT_LOGGING
   223     nsTraceRefcnt::SetActivityIsLegal(false);
   224 #endif
   226 #if 0
   227     // XXXbsmedberg: do this as soon as the static-destructor crash(es)
   228     // are fixed
   229     PRStatus ret = PR_UnloadLibrary(aLoadData.library);
   230     NS_ASSERTION(ret == PR_SUCCESS, "Failed to unload library");
   231 #endif
   233 #ifdef NS_BUILD_REFCNT_LOGGING
   234     nsTraceRefcnt::SetActivityIsLegal(true);
   235 #endif
   237     return PL_DHASH_REMOVE;
   238 }
   240 void
   241 nsNativeModuleLoader::UnloadLibraries()
   242 {
   243     MOZ_ASSERT(NS_IsMainThread(), "Shutdown not on main thread?");
   244     mLibraries.Enumerate(ReleaserFunc, nullptr);
   245     mLibraries.Enumerate(UnloaderFunc, nullptr);
   246 }

mercurial