diff --git a/browser/app/nsBrowserApp.cpp b/browser/app/nsBrowserApp.cpp index 91efa3f978de..4957b4244ebd 100644 --- a/browser/app/nsBrowserApp.cpp +++ b/browser/app/nsBrowserApp.cpp @@ -5,6 +5,7 @@ #include "nsXULAppAPI.h" #include "mozilla/XREAppData.h" +#include "XREChildData.h" #include "XREShellData.h" #include "application.ini.h" #include "mozilla/Bootstrap.h" @@ -38,9 +39,12 @@ # include "mozilla/WindowsProcessMitigations.h" # define XRE_WANT_ENVIRON +# include "nsWindowsWMain.cpp" + # define strcasecmp _stricmp # ifdef MOZ_SANDBOX # include "mozilla/sandboxing/SandboxInitialization.h" +# include "mozilla/sandboxing/sandboxLogging.h" # endif #endif #include "BinaryPath.h" @@ -97,7 +101,6 @@ __attribute__((constructor)) static void SSE2Check() { #if !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) # define MOZ_BROWSER_CAN_BE_CONTENTPROC -# include "../../ipc/contentproc/plugin-container.cpp" #endif using namespace mozilla; @@ -280,30 +283,38 @@ int main(int argc, char* argv[], char* envp[]) { #if defined(XP_UNIX) ReserveDefaultFileDescriptors(); #endif -#if defined(MOZ_ENABLE_FORKSERVER) - if (strcmp(argv[argc - 1], "forkserver") == 0) { - nsresult rv = InitXPCOMGlue(LibLoadingStrategy::NoReadAhead); - if (NS_FAILED(rv)) { - return 255; - } - // Run a fork server in this process, single thread. When it - // returns, it means the fork server have been stopped or a new - // content process is created. - // - // For the later case, XRE_ForkServer() will return false, running - // in a content process just forked from the fork server process. - // argc & argv will be updated with the values passing from the - // chrome process. With the new values, this function - // continues the reset of the code acting as a content process. - if (gBootstrap->XRE_ForkServer(&argc, &argv)) { - // Return from the fork server in the fork server process. - // Stop the fork server. - gBootstrap->NS_LogTerm(); - return 0; +#ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC + if (argc > 1 && IsArg(argv[1], "contentproc")) { + // Set the process type and gecko child id. + SetGeckoProcessType(argv[--argc]); + SetGeckoChildID(argv[--argc]); + +# if defined(MOZ_ENABLE_FORKSERVER) + if (GetGeckoProcessType() == GeckoProcessType_ForkServer) { + nsresult rv = InitXPCOMGlue(LibLoadingStrategy::NoReadAhead); + if (NS_FAILED(rv)) { + return 255; + } + + // Run a fork server in this process, single thread. When it returns, it + // means the fork server have been stopped or a new child process is + // created. + // + // For the latter case, XRE_ForkServer() will return false, running in a + // child process just forked from the fork server process. argc & argv + // will be updated with the values passing from the chrome process, as + // will GeckoProcessType and GeckoChildID. With the new values, this + // function continues the reset of the code acting as a child process. + if (gBootstrap->XRE_ForkServer(&argc, &argv)) { + // Return from the fork server in the fork server process. + // Stop the fork server. + // InitXPCOMGlue calls NS_LogInit, so we need to balance it here. + gBootstrap->NS_LogTerm(); + return 0; + } } - // In a content process forked from the fork server. - // Start acting as a content process. +# endif } #endif @@ -312,25 +323,19 @@ int main(int argc, char* argv[], char* envp[]) { AUTO_BASE_PROFILER_INIT; AUTO_BASE_PROFILER_LABEL("nsBrowserApp main", OTHER); + // Register an external module to report on otherwise uncatchable exceptions. + // Note that in child processes this must be called after Gecko process type + // has been set. + CrashReporter::RegisterRuntimeExceptionModule(); + // Make sure we unregister the runtime exception module before returning. - // We do this here to cover both registers for child and main processes. auto unregisterRuntimeExceptionModule = MakeScopeExit([] { CrashReporter::UnregisterRuntimeExceptionModule(); }); #ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC // We are launching as a content process, delegate to the appropriate // main - if (argc > 1 && IsArg(argv[1], "contentproc")) { - // Set the process type and gecko child id. We don't remove the args here as - // that will be done later in common code. - SetGeckoProcessType(argv[argc - 1]); - SetGeckoChildID(argv[argc - 2]); - - // Register an external module to report on otherwise uncatchable - // exceptions. Note that in child processes this must be called after Gecko - // process type has been set. - CrashReporter::RegisterRuntimeExceptionModule(); - + if (GetGeckoProcessType() != GeckoProcessType_Default) { # if defined(XP_WIN) && defined(MOZ_SANDBOX) // We need to set whether our process is supposed to have win32k locked down // from the command line setting before DllBlocklist_Initialize, @@ -376,7 +381,26 @@ int main(int argc, char* argv[], char* envp[]) { return 255; } - int result = content_process_main(gBootstrap.get(), argc, argv); + XREChildData childData; + +# if defined(XP_WIN) && defined(MOZ_SANDBOX) + if (IsSandboxedProcess()) { + childData.sandboxTargetServices = + mozilla::sandboxing::GetInitializedTargetServices(); + if (!childData.sandboxTargetServices) { + return 1; + } + + childData.ProvideLogFunction = mozilla::sandboxing::ProvideLogFunction; + } + + if (GetGeckoProcessType() == GeckoProcessType_RemoteSandboxBroker) { + childData.sandboxBrokerServices = + mozilla::sandboxing::GetInitializedBrokerServices(); + } +# endif + + rv = gBootstrap->XRE_InitChildProcess(argc, argv, &childData); # if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST) DllBlocklist_Shutdown(); @@ -385,13 +409,10 @@ int main(int argc, char* argv[], char* envp[]) { // InitXPCOMGlue calls NS_LogInit, so we need to balance it here. gBootstrap->NS_LogTerm(); - return result; + return NS_FAILED(rv) ? 1 : 0; } #endif - // Register an external module to report on otherwise uncatchable exceptions. - CrashReporter::RegisterRuntimeExceptionModule(); - #ifdef HAS_DLL_BLOCKLIST DllBlocklist_Initialize(gBlocklistInitFlags); #endif diff --git a/ipc/app/MozillaRuntimeMain.cpp b/ipc/app/MozillaRuntimeMain.cpp index df157987884a..68eae06910bb 100644 --- a/ipc/app/MozillaRuntimeMain.cpp +++ b/ipc/app/MozillaRuntimeMain.cpp @@ -4,59 +4,34 @@ * 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/. */ -#include "../contentproc/plugin-container.cpp" - +#include "nsXULAppAPI.h" +#include "XREChildData.h" #include "mozilla/Bootstrap.h" +#include "mozilla/ProcessType.h" #include "mozilla/RuntimeExceptionModule.h" #include "mozilla/ScopeExit.h" #if defined(XP_WIN) # include "mozilla/WindowsDllBlocklist.h" # include "mozilla/GeckoArgs.h" + +# include "nsWindowsWMain.cpp" + +# ifdef MOZ_SANDBOX +# include "mozilla/sandboxing/SandboxInitialization.h" +# include "mozilla/sandboxing/sandboxLogging.h" +# endif #endif // defined(XP_WIN) using namespace mozilla; -static bool UseForkServer(int argc, char* argv[]) { -#if defined(MOZ_ENABLE_FORKSERVER) - return strcmp(argv[argc - 1], "forkserver") == 0; -#else - return false; -#endif -} - -static int RunForkServer(Bootstrap::UniquePtr&& bootstrap, int argc, - char* argv[]) { -#if defined(MOZ_ENABLE_FORKSERVER) - int ret = 0; - - bootstrap->NS_LogInit(); - - // Run a fork server in this process, single thread. When it - // returns, it means the fork server have been stopped or a new - // content process is created. - // - // For the later case, XRE_ForkServer() will return false, running - // in a content process just forked from the fork server process. - // argc & argv will be updated with the values passing from the - // chrome process. With the new values, this function - // continues the reset of the code acting as a content process. - if (bootstrap->XRE_ForkServer(&argc, &argv)) { - // Return from the fork server in the fork server process. - // Stop the fork server. - } else { - // In a content process forked from the fork server. - // Start acting as a content process. - ret = content_process_main(bootstrap.get(), argc, argv); - } - - bootstrap->NS_LogTerm(); - return ret; -#else - return 0; -#endif -} - int main(int argc, char* argv[]) { + // Set the process type and gecko child id. + if (argc < 2) { + return 3; + } + SetGeckoProcessType(argv[--argc]); + SetGeckoChildID(argv[--argc]); + auto bootstrapResult = GetBootstrap(); if (bootstrapResult.isErr()) { return 2; @@ -64,36 +39,67 @@ int main(int argc, char* argv[]) { Bootstrap::UniquePtr bootstrap = bootstrapResult.unwrap(); - int ret; - if (UseForkServer(argc, argv)) { - ret = RunForkServer(std::move(bootstrap), argc, argv); - } else { - // Set the process type and gecko child id. We don't remove the args here as - // that will be done later in common code. - SetGeckoProcessType(argv[argc - 1]); - SetGeckoChildID(argv[argc - 2]); +#if defined(MOZ_ENABLE_FORKSERVER) + if (GetGeckoProcessType() == GeckoProcessType_ForkServer) { + bootstrap->NS_LogInit(); - // Register an external module to report on otherwise uncatchable - // exceptions. Note that in child processes this must be called after Gecko - // process type has been set. - CrashReporter::RegisterRuntimeExceptionModule(); + // Run a fork server in this process, single thread. When it returns, it + // means the fork server have been stopped or a new child process is + // created. + // + // For the latter case, XRE_ForkServer() will return false, running in a + // child process just forked from the fork server process. argc & argv will + // be updated with the values passing from the chrome process, as will + // GeckoProcessType and GeckoChildID. With the new values, this function + // continues the reset of the code acting as a child process. + if (bootstrap->XRE_ForkServer(&argc, &argv)) { + // Return from the fork server in the fork server process. + // Stop the fork server. + bootstrap->NS_LogTerm(); + return 0; + } + } +#endif - // Make sure we unregister the runtime exception module before returning. - auto unregisterRuntimeExceptionModule = MakeScopeExit( - [] { CrashReporter::UnregisterRuntimeExceptionModule(); }); + // Register an external module to report on otherwise uncatchable + // exceptions. Note that in child processes this must be called after Gecko + // process type has been set. + CrashReporter::RegisterRuntimeExceptionModule(); + + // Make sure we unregister the runtime exception module before returning. + auto unregisterRuntimeExceptionModule = + MakeScopeExit([] { CrashReporter::UnregisterRuntimeExceptionModule(); }); #ifdef HAS_DLL_BLOCKLIST - uint32_t initFlags = eDllBlocklistInitFlagIsChildProcess; - SetDllBlocklistProcessTypeFlags(initFlags, GetGeckoProcessType()); - DllBlocklist_Initialize(initFlags); + uint32_t initFlags = eDllBlocklistInitFlagIsChildProcess; + SetDllBlocklistProcessTypeFlags(initFlags, GetGeckoProcessType()); + DllBlocklist_Initialize(initFlags); #endif - ret = content_process_main(bootstrap.get(), argc, argv); + XREChildData childData; -#if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST) - DllBlocklist_Shutdown(); -#endif +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + if (IsSandboxedProcess()) { + childData.sandboxTargetServices = + mozilla::sandboxing::GetInitializedTargetServices(); + if (!childData.sandboxTargetServices) { + return 1; + } + + childData.ProvideLogFunction = mozilla::sandboxing::ProvideLogFunction; } - return ret; + if (GetGeckoProcessType() == GeckoProcessType_RemoteSandboxBroker) { + childData.sandboxBrokerServices = + mozilla::sandboxing::GetInitializedBrokerServices(); + } +#endif + + nsresult rv = bootstrap->XRE_InitChildProcess(argc, argv, &childData); + +#if defined(DEBUG) && defined(HAS_DLL_BLOCKLIST) + DllBlocklist_Shutdown(); +#endif + + return NS_FAILED(rv) ? 1 : 0; } diff --git a/ipc/contentproc/plugin-container.cpp b/ipc/contentproc/plugin-container.cpp deleted file mode 100644 index 93371ab39581..000000000000 --- a/ipc/contentproc/plugin-container.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=4 et : - * 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/. */ - -#include "nsXPCOM.h" -#include "nsXULAppAPI.h" -#include "mozilla/Bootstrap.h" -#include "mozilla/ProcessType.h" -#include "XREChildData.h" - -#ifdef XP_WIN -# include -// we want a wmain entry point -# include "nsWindowsWMain.cpp" -#else -// FIXME/cjones testing -# include -#endif - -#if defined(XP_WIN) && defined(MOZ_SANDBOX) -# include "mozilla/sandboxing/SandboxInitialization.h" -# include "mozilla/sandboxing/sandboxLogging.h" -#endif - -int content_process_main(mozilla::Bootstrap* bootstrap, int argc, - char* argv[]) { - // Check for the absolute minimum number of args we need to move - // forward here. We expect the last arg to be the child process type, and the - // second-last argument to be the gecko child id. - if (argc < 2) { - return 3; - } - - XREChildData childData; - -#if defined(XP_WIN) && defined(MOZ_SANDBOX) - if (IsSandboxedProcess()) { - childData.sandboxTargetServices = - mozilla::sandboxing::GetInitializedTargetServices(); - if (!childData.sandboxTargetServices) { - return 1; - } - - childData.ProvideLogFunction = mozilla::sandboxing::ProvideLogFunction; - } -#endif - - mozilla::SetGeckoProcessType(argv[--argc]); - mozilla::SetGeckoChildID(argv[--argc]); - -#if defined(XP_WIN) && defined(MOZ_SANDBOX) - if (mozilla::GetGeckoProcessType() == GeckoProcessType_RemoteSandboxBroker) { - childData.sandboxBrokerServices = - mozilla::sandboxing::GetInitializedBrokerServices(); - } -#endif - - nsresult rv = bootstrap->XRE_InitChildProcess(argc, argv, &childData); - return NS_FAILED(rv); -} diff --git a/ipc/glue/ForkServer.cpp b/ipc/glue/ForkServer.cpp index e3a814297ecc..a50e442a828b 100644 --- a/ipc/glue/ForkServer.cpp +++ b/ipc/glue/ForkServer.cpp @@ -249,6 +249,8 @@ void ForkServer::OnMessageReceived(UniquePtr message) { * arguments from the chrome process. */ bool ForkServer::RunForkServer(int* aArgc, char*** aArgv) { + MOZ_ASSERT(XRE_IsForkServerProcess(), "fork server process only"); + #ifdef DEBUG if (getenv("MOZ_FORKSERVER_WAIT_GDB")) { printf( @@ -262,12 +264,6 @@ bool ForkServer::RunForkServer(int* aArgc, char*** aArgv) { SetProcessTitleInit(*aArgv); - // The last two arguments are the GeckoChildID and "forkserver". - MOZ_ASSERT(!strcmp((*aArgv)[*aArgc - 1], "forkserver"), - "last argument is not \"forkserver\""); - SetGeckoProcessType("forkserver"); - SetGeckoChildID((*aArgv)[*aArgc - 2]); - // Do this before NS_LogInit() to avoid log files taking lower // FDs. ForkServer forkserver; @@ -319,8 +315,17 @@ bool ForkServer::RunForkServer(int* aArgc, char*** aArgv) { forkserver.mAppProcBuilder->InitAppProcess(aArgc, aArgv); forkserver.mAppProcBuilder.reset(); + // Update our GeckoProcessType and GeckoChildID, removing the arguments. + if (*aArgc < 2) { + MOZ_CRASH("forked process missing process type and childid arguments"); + } + SetGeckoProcessType((*aArgv)[--*aArgc]); + SetGeckoChildID((*aArgv)[--*aArgc]); + MOZ_ASSERT(!XRE_IsForkServerProcess(), + "fork server created another fork server?"); + // Open log files again with right names and the new PID. - nsTraceRefcnt::ReopenLogFilesAfterFork((*aArgv)[*aArgc - 1]); + nsTraceRefcnt::ReopenLogFilesAfterFork(XRE_GetProcessTypeString()); return false; } diff --git a/mozglue/android/APKOpen.cpp b/mozglue/android/APKOpen.cpp index 80386f3a92ce..963d97a1ba86 100644 --- a/mozglue/android/APKOpen.cpp +++ b/mozglue/android/APKOpen.cpp @@ -393,6 +393,11 @@ Java_org_mozilla_gecko_mozglue_GeckoLoader_nativeRun( ElfLoader::Singleton.ExpectShutdown(true); #endif } else { + if (argc < 2) { + FreeArgv(argv, argc); + return; + } + SetGeckoProcessType(argv[--argc]); SetGeckoChildID(argv[--argc]); @@ -416,6 +421,12 @@ extern "C" APKOPEN_EXPORT mozglueresult ChildProcessInit(int argc, char* argv[]) { EnsureBaseProfilerInitialized(); + if (argc < 2) { + return FAILURE; + } + SetGeckoProcessType(argv[--argc]); + SetGeckoChildID(argv[--argc]); + if (loadNSSLibs() != SUCCESS) { return FAILURE; } @@ -426,9 +437,6 @@ extern "C" APKOPEN_EXPORT mozglueresult ChildProcessInit(int argc, return FAILURE; } - SetGeckoProcessType(argv[--argc]); - SetGeckoChildID(argv[--argc]); - XREChildData childData; return NS_FAILED(gBootstrap->XRE_InitChildProcess(argc, argv, &childData)); } diff --git a/mozglue/misc/ProcessType.cpp b/mozglue/misc/ProcessType.cpp index 429626c4c4d6..3c82d6a46637 100644 --- a/mozglue/misc/ProcessType.cpp +++ b/mozglue/misc/ProcessType.cpp @@ -19,24 +19,15 @@ GeckoChildID sGeckoChildID = 0; } // namespace startup void SetGeckoProcessType(const char* aProcessTypeString) { -#if !defined(DEBUG) - // If not a DEBUG build then just return if sChildProcessType has already been - // set and is not fork server. In DEBUG builds we will check that process type - // matches the one already set if it is not fork server. if (sChildProcessType != GeckoProcessType_Default && sChildProcessType != GeckoProcessType_ForkServer) { - return; + MOZ_CRASH("Cannot set GeckoProcessType multiple times."); } -#endif #define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \ process_bin_type, procinfo_typename, \ webidl_typename, allcaps_name) \ if (std::strcmp(aProcessTypeString, string_name) == 0) { \ - MOZ_ASSERT_IF( \ - sChildProcessType != GeckoProcessType_Default && \ - sChildProcessType != GeckoProcessType_ForkServer, \ - sChildProcessType == GeckoProcessType::GeckoProcessType_##enum_name); \ sChildProcessType = GeckoProcessType::GeckoProcessType_##enum_name; \ return; \ } @@ -58,6 +49,10 @@ void SetGeckoProcessType(const char* aProcessTypeString) { void SetGeckoChildID(const char* aGeckoChildIDString) { sGeckoChildID = atoi(aGeckoChildIDString); + + if (sGeckoChildID <= 0) { + MOZ_CRASH("aGeckoChildIDString is not valid."); + } } } // namespace mozilla