2016-05-27 21:54:31 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* 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/. */
|
2009-06-29 18:38:29 +00:00
|
|
|
|
|
|
|
#include "GeckoChildProcessHost.h"
|
|
|
|
|
|
|
|
#include "base/command_line.h"
|
2009-07-10 19:03:09 +00:00
|
|
|
#include "base/string_util.h"
|
2016-05-12 22:15:43 +00:00
|
|
|
#include "base/task.h"
|
2009-06-29 18:38:29 +00:00
|
|
|
#include "chrome/common/chrome_switches.h"
|
2009-11-19 19:03:30 +00:00
|
|
|
#include "chrome/common/process_watcher.h"
|
2011-10-14 07:54:46 +00:00
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
2010-09-10 17:09:30 +00:00
|
|
|
# include "chrome/common/mach_ipc_mac.h"
|
|
|
|
# include "base/rand_util.h"
|
2010-09-16 06:09:19 +00:00
|
|
|
# include "nsILocalFileMac.h"
|
2015-06-17 04:38:38 +00:00
|
|
|
# include "SharedMemoryBasic.h"
|
2010-09-10 17:09:30 +00:00
|
|
|
#endif
|
2009-06-29 18:38:29 +00:00
|
|
|
|
2014-04-04 19:16:16 +00:00
|
|
|
#include "MainThreadUtils.h"
|
2016-08-15 06:43:21 +00:00
|
|
|
#include "mozilla/Sprintf.h"
|
2011-03-25 23:40:50 +00:00
|
|
|
#include "prenv.h"
|
2014-07-17 15:15:09 +00:00
|
|
|
#include "nsXPCOMPrivate.h"
|
2009-10-27 21:52:37 +00:00
|
|
|
|
2019-03-18 22:31:59 +00:00
|
|
|
#if defined(MOZ_SANDBOX)
|
2017-05-12 21:04:42 +00:00
|
|
|
# include "mozilla/SandboxSettings.h"
|
2016-08-30 20:32:21 +00:00
|
|
|
# include "nsAppDirectoryServiceDefs.h"
|
|
|
|
#endif
|
|
|
|
|
2010-01-12 21:14:38 +00:00
|
|
|
#include "nsExceptionHandler.h"
|
|
|
|
|
2010-04-09 20:03:08 +00:00
|
|
|
#include "nsDirectoryServiceDefs.h"
|
|
|
|
#include "nsIFile.h"
|
2016-03-10 08:07:57 +00:00
|
|
|
#include "nsPrintfCString.h"
|
2019-02-05 00:15:22 +00:00
|
|
|
#include "nsIObserverService.h"
|
2010-04-09 20:03:08 +00:00
|
|
|
|
2010-02-03 22:17:09 +00:00
|
|
|
#include "mozilla/ipc/BrowserProcessSubThread.h"
|
2018-01-08 09:07:16 +00:00
|
|
|
#include "mozilla/ipc/EnvironmentMap.h"
|
2010-06-25 20:29:43 +00:00
|
|
|
#include "mozilla/Omnijar.h"
|
2019-02-05 00:15:22 +00:00
|
|
|
#include "mozilla/RecordReplay.h"
|
2019-03-28 02:25:50 +00:00
|
|
|
#include "mozilla/RDDProcessHost.h"
|
2018-12-19 15:29:09 +00:00
|
|
|
#include "mozilla/Scoped.h"
|
2019-02-05 00:15:22 +00:00
|
|
|
#include "mozilla/Services.h"
|
|
|
|
#include "mozilla/SharedThreadPool.h"
|
|
|
|
#include "mozilla/StaticMutex.h"
|
2016-06-01 22:13:59 +00:00
|
|
|
#include "mozilla/Telemetry.h"
|
2015-04-01 08:40:35 +00:00
|
|
|
#include "ProtocolUtils.h"
|
2010-06-25 18:39:02 +00:00
|
|
|
#include <sys/stat.h>
|
2009-07-20 18:14:41 +00:00
|
|
|
|
2010-05-15 00:25:10 +00:00
|
|
|
#ifdef XP_WIN
|
|
|
|
# include "nsIWinTaskbar.h"
|
2017-03-06 16:42:31 +00:00
|
|
|
# include <stdlib.h>
|
2010-05-15 00:25:10 +00:00
|
|
|
# define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
|
2019-01-18 09:16:18 +00:00
|
|
|
|
2014-11-29 17:12:18 +00:00
|
|
|
# if defined(MOZ_SANDBOX)
|
2014-06-11 14:32:37 +00:00
|
|
|
# include "mozilla/Preferences.h"
|
2014-11-29 17:12:18 +00:00
|
|
|
# include "mozilla/sandboxing/sandboxLogging.h"
|
2017-06-23 15:29:15 +00:00
|
|
|
# include "WinUtils.h"
|
2019-03-13 09:24:52 +00:00
|
|
|
# if defined(_ARM64_)
|
|
|
|
# include "mozilla/remoteSandboxBroker.h"
|
|
|
|
# endif
|
2014-06-11 14:32:37 +00:00
|
|
|
# endif
|
2010-05-15 00:25:10 +00:00
|
|
|
#endif
|
|
|
|
|
2017-01-31 01:49:53 +00:00
|
|
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
2017-10-06 23:15:46 +00:00
|
|
|
# include "mozilla/SandboxLaunch.h"
|
2017-01-31 01:49:53 +00:00
|
|
|
#endif
|
|
|
|
|
2019-03-28 02:25:52 +00:00
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
|
|
# include "nsMacUtilsImpl.h"
|
|
|
|
#endif
|
|
|
|
|
2013-05-31 13:16:54 +00:00
|
|
|
#include "nsTArray.h"
|
|
|
|
#include "nsClassHashtable.h"
|
|
|
|
#include "nsHashKeys.h"
|
2014-07-17 15:15:09 +00:00
|
|
|
#include "nsNativeCharsetUtils.h"
|
2015-07-31 19:11:48 +00:00
|
|
|
#include "nscore.h" // for NS_FREE_PERMANENT_DATA
|
2017-11-27 20:37:34 +00:00
|
|
|
#include "private/pprio.h"
|
2013-05-31 13:16:54 +00:00
|
|
|
|
2011-04-29 19:21:57 +00:00
|
|
|
using mozilla::MonitorAutoLock;
|
2019-03-28 02:25:52 +00:00
|
|
|
using mozilla::Preferences;
|
2019-02-05 00:15:22 +00:00
|
|
|
using mozilla::StaticMutexAutoLock;
|
2009-06-29 18:38:29 +00:00
|
|
|
using mozilla::ipc::GeckoChildProcessHost;
|
|
|
|
|
2018-12-19 15:29:09 +00:00
|
|
|
namespace mozilla {
|
|
|
|
MOZ_TYPE_SPECIFIC_SCOPED_POINTER_TEMPLATE(ScopedPRFileDesc, PRFileDesc,
|
|
|
|
PR_Close)
|
|
|
|
}
|
|
|
|
|
|
|
|
using mozilla::ScopedPRFileDesc;
|
|
|
|
|
2015-05-14 21:20:57 +00:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
# include "AndroidBridge.h"
|
2016-10-05 23:37:35 +00:00
|
|
|
# include "GeneratedJNIWrappers.h"
|
|
|
|
# include "mozilla/jni/Refs.h"
|
|
|
|
# include "mozilla/jni/Utils.h"
|
2015-05-14 21:20:57 +00:00
|
|
|
#endif
|
|
|
|
|
2011-06-03 18:33:55 +00:00
|
|
|
static bool ShouldHaveDirectoryService() {
|
|
|
|
return GeckoProcessType_Default == XRE_GetProcessType();
|
|
|
|
}
|
|
|
|
|
2009-09-03 00:18:27 +00:00
|
|
|
GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
2017-09-08 22:16:50 +00:00
|
|
|
bool aIsFileContent)
|
2016-06-02 00:00:37 +00:00
|
|
|
: mProcessType(aProcessType),
|
2017-09-08 22:16:50 +00:00
|
|
|
mIsFileContent(aIsFileContent),
|
2011-04-29 19:21:57 +00:00
|
|
|
mMonitor("mozilla.ipc.GeckChildProcessHost.mMonitor"),
|
2017-09-09 02:35:06 +00:00
|
|
|
mLaunchOptions(MakeUnique<base::LaunchOptions>()),
|
2012-08-07 23:29:32 +00:00
|
|
|
mProcessState(CREATING_CHANNEL),
|
Bug 1447246 - Refactor ContentProcess::Init(). r=jimm
The current code is a bit of a mess. This patch does the following.
- Changes the processing from backwards to forwards. This avoids the need for
all the `found` booleans, because if a flag is present multiple times, the
last one will naturally override.
- Tightens up the checking. It now doesn't use assertions, but instead returns
false if any of the options are missing arguments, or have malformed
arguments, or any of the mandatory flags are missing. (It assumes that
-appdir and -profile are optional.)
- Renames the loop variable `idx` as `i`.
- Changes `!strcmp(...)` to `strcmp(...) == 0`, because I find that clearer.
- Avoids a redundant nsCString when handling -appdir.
The patch also tweaks GeckoChildProcessHost::mGroupId, which was buggy. It
holds the appModelUserId argument, which XRE_InitChildProcess() always expects
is present in the command. But it's only set to a non-empty value in
InitWindowsGroupID(), which is only called for plugin processes. So in lots of
cases the appModelUserId argument was missing, and a different argument would
be interpreted as the appModelUserId argument (seemingly without noticeable ill
effect).
The patch changes things to mGroupId defaults to "-", which means it's always
present in the command.
Note: all this explains why the old code for ContentProcess::Init() started
processing from argument aArgc, instead of aArgc-1 as you might expect -- it
had to read one extra arg in order to see the argument following -appdir,
because XRE_InitChildProcess() was decrementing aArgc for the appModelUserId
argument even when that argument wasn't present. The new code for
ContentProcess::Init() doesn't have to read past aArgc-1 because the mGroupId
fix ensures the appModelUserId argument is always present.
MozReview-Commit-ID: 8a8k6ABYMgo
--HG--
extra : rebase_source : 70695125ee26e67af3337119f4dfc293a0dab74c
2018-03-16 01:23:10 +00:00
|
|
|
#ifdef XP_WIN
|
|
|
|
mGroupId(u"-"),
|
|
|
|
#endif
|
2014-11-29 17:12:18 +00:00
|
|
|
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
|
|
|
|
mEnableSandboxLogging(false),
|
2015-01-30 17:48:15 +00:00
|
|
|
mSandboxLevel(0),
|
2014-06-11 14:32:37 +00:00
|
|
|
#endif
|
2019-02-05 00:15:20 +00:00
|
|
|
mChildProcessHandle(0),
|
2011-10-14 07:54:46 +00:00
|
|
|
#if defined(MOZ_WIDGET_COCOA)
|
2019-02-05 00:15:20 +00:00
|
|
|
mChildTask(MACH_PORT_NULL),
|
2010-08-27 13:32:45 +00:00
|
|
|
#endif
|
2019-02-05 00:15:20 +00:00
|
|
|
mDestroying(false) {
|
2009-11-09 22:56:55 +00:00
|
|
|
MOZ_COUNT_CTOR(GeckoChildProcessHost);
|
|
|
|
}
|
|
|
|
|
|
|
|
GeckoChildProcessHost::~GeckoChildProcessHost()
|
2009-12-19 00:09:56 +00:00
|
|
|
|
2009-11-09 22:56:55 +00:00
|
|
|
{
|
2009-12-19 00:09:56 +00:00
|
|
|
AssertIOThread();
|
2019-02-05 00:15:20 +00:00
|
|
|
MOZ_RELEASE_ASSERT(mDestroying);
|
2009-12-19 00:09:56 +00:00
|
|
|
|
|
|
|
MOZ_COUNT_DTOR(GeckoChildProcessHost);
|
2009-11-19 19:03:30 +00:00
|
|
|
|
2016-10-26 03:08:11 +00:00
|
|
|
if (mChildProcessHandle != 0) {
|
2015-06-17 04:38:38 +00:00
|
|
|
#if defined(MOZ_WIDGET_COCOA)
|
|
|
|
SharedMemoryBasic::CleanupForPid(mChildProcessHandle);
|
|
|
|
#endif
|
2010-01-13 20:57:52 +00:00
|
|
|
ProcessWatcher::EnsureProcessTerminated(
|
|
|
|
mChildProcessHandle
|
2015-07-31 19:11:48 +00:00
|
|
|
#ifdef NS_FREE_PERMANENT_DATA
|
2015-07-27 19:49:48 +00:00
|
|
|
// If we're doing leak logging, shutdown can be slow.
|
2010-01-13 20:57:52 +00:00
|
|
|
,
|
|
|
|
false // don't "force"
|
|
|
|
#endif
|
|
|
|
);
|
2015-06-17 04:38:38 +00:00
|
|
|
}
|
2010-08-27 13:32:45 +00:00
|
|
|
|
2011-10-14 07:54:46 +00:00
|
|
|
#if defined(MOZ_WIDGET_COCOA)
|
2010-08-27 13:32:45 +00:00
|
|
|
if (mChildTask != MACH_PORT_NULL)
|
|
|
|
mach_port_deallocate(mach_task_self(), mChildTask);
|
|
|
|
#endif
|
2017-11-27 20:37:34 +00:00
|
|
|
|
|
|
|
if (mChildProcessHandle != 0) {
|
|
|
|
#if defined(XP_WIN)
|
|
|
|
CrashReporter::DeregisterChildCrashAnnotationFileDescriptor(
|
|
|
|
base::GetProcId(mChildProcessHandle));
|
|
|
|
#else
|
|
|
|
CrashReporter::DeregisterChildCrashAnnotationFileDescriptor(
|
|
|
|
mChildProcessHandle);
|
|
|
|
#endif
|
|
|
|
}
|
2019-03-13 09:24:52 +00:00
|
|
|
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
|
|
|
|
if (mSandboxBroker) {
|
|
|
|
mSandboxBroker->Shutdown();
|
|
|
|
mSandboxBroker = nullptr;
|
|
|
|
}
|
|
|
|
#endif
|
2009-07-20 18:14:41 +00:00
|
|
|
}
|
|
|
|
|
2019-02-05 00:15:20 +00:00
|
|
|
void GeckoChildProcessHost::Destroy() {
|
|
|
|
MOZ_RELEASE_ASSERT(!mDestroying);
|
|
|
|
RefPtr<HandlePromise> whenReady = mHandlePromise;
|
|
|
|
|
|
|
|
if (!whenReady) {
|
|
|
|
// AsyncLaunch not called yet, so dispatch immediately.
|
|
|
|
whenReady = HandlePromise::CreateAndReject(LaunchError{}, __func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
using Value = HandlePromise::ResolveOrRejectValue;
|
|
|
|
mDestroying = true;
|
|
|
|
whenReady->Then(XRE_GetIOMessageLoop()->SerialEventTarget(), __func__,
|
|
|
|
[this](const Value&) { delete this; });
|
|
|
|
}
|
|
|
|
|
2014-04-04 19:16:16 +00:00
|
|
|
// static
|
2019-04-08 20:19:51 +00:00
|
|
|
mozilla::BinPathType GeckoChildProcessHost::GetPathToBinary(FilePath& exePath,
|
|
|
|
GeckoProcessType processType) {
|
|
|
|
BinPathType pathType = XRE_GetChildProcBinPathType(processType);
|
|
|
|
|
|
|
|
if (pathType == BinPathType::Self) {
|
2016-06-03 19:49:39 +00:00
|
|
|
#if defined(OS_WIN)
|
|
|
|
wchar_t exePathBuf[MAXPATHLEN];
|
|
|
|
if (!::GetModuleFileNameW(nullptr, exePathBuf, MAXPATHLEN)) {
|
|
|
|
MOZ_CRASH("GetModuleFileNameW failed (FIXME)");
|
|
|
|
}
|
2017-07-29 08:29:56 +00:00
|
|
|
# if defined(MOZ_SANDBOX)
|
|
|
|
// We need to start the child process using the real path, so that the
|
|
|
|
// sandbox policy rules will match for DLLs loaded from the bin dir after
|
|
|
|
// we have lowered the sandbox.
|
2017-08-07 16:27:10 +00:00
|
|
|
std::wstring exePathStr = exePathBuf;
|
|
|
|
if (widget::WinUtils::ResolveJunctionPointsAndSymLinks(exePathStr)) {
|
|
|
|
exePath = FilePath::FromWStringHack(exePathStr);
|
|
|
|
} else
|
2017-07-29 08:29:56 +00:00
|
|
|
# endif
|
2017-08-07 16:27:10 +00:00
|
|
|
{
|
|
|
|
exePath = FilePath::FromWStringHack(exePathBuf);
|
|
|
|
}
|
2016-06-03 19:49:39 +00:00
|
|
|
#elif defined(OS_POSIX)
|
|
|
|
exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
|
|
|
|
#else
|
|
|
|
# error Sorry; target OS not supported yet.
|
|
|
|
#endif
|
2019-04-08 20:19:51 +00:00
|
|
|
return pathType;
|
2016-06-03 19:49:39 +00:00
|
|
|
}
|
|
|
|
|
2011-06-03 18:33:55 +00:00
|
|
|
if (ShouldHaveDirectoryService()) {
|
2014-10-10 19:06:57 +00:00
|
|
|
MOZ_ASSERT(gGREBinPath);
|
2012-07-10 22:31:04 +00:00
|
|
|
#ifdef OS_WIN
|
2014-10-10 19:06:57 +00:00
|
|
|
exePath = FilePath(char16ptr_t(gGREBinPath));
|
2014-09-29 18:51:04 +00:00
|
|
|
#elif MOZ_WIDGET_COCOA
|
|
|
|
nsCOMPtr<nsIFile> childProcPath;
|
2014-10-10 19:06:57 +00:00
|
|
|
NS_NewLocalFile(nsDependentString(gGREBinPath), false,
|
2014-09-29 18:51:04 +00:00
|
|
|
getter_AddRefs(childProcPath));
|
2016-06-03 19:49:39 +00:00
|
|
|
|
2014-09-29 18:51:04 +00:00
|
|
|
// We need to use an App Bundle on OS X so that we can hide
|
|
|
|
// the dock icon. See Bug 557225.
|
2016-04-08 17:34:40 +00:00
|
|
|
childProcPath->AppendNative(NS_LITERAL_CSTRING("plugin-container.app"));
|
2014-09-29 18:51:04 +00:00
|
|
|
childProcPath->AppendNative(NS_LITERAL_CSTRING("Contents"));
|
|
|
|
childProcPath->AppendNative(NS_LITERAL_CSTRING("MacOS"));
|
|
|
|
nsCString tempCPath;
|
|
|
|
childProcPath->GetNativePath(tempCPath);
|
|
|
|
exePath = FilePath(tempCPath.get());
|
2012-07-10 22:31:04 +00:00
|
|
|
#else
|
2014-07-17 15:15:09 +00:00
|
|
|
nsCString path;
|
2014-10-10 19:06:57 +00:00
|
|
|
NS_CopyUnicodeToNative(nsDependentString(gGREBinPath), path);
|
2014-07-17 15:15:09 +00:00
|
|
|
exePath = FilePath(path.get());
|
2011-09-07 04:51:38 +00:00
|
|
|
#endif
|
2010-09-16 06:09:19 +00:00
|
|
|
}
|
2011-09-07 04:51:38 +00:00
|
|
|
|
2011-06-03 18:33:55 +00:00
|
|
|
if (exePath.empty()) {
|
2012-07-10 22:31:04 +00:00
|
|
|
#ifdef OS_WIN
|
|
|
|
exePath =
|
|
|
|
FilePath::FromWStringHack(CommandLine::ForCurrentProcess()->program());
|
|
|
|
#else
|
2010-09-16 06:09:19 +00:00
|
|
|
exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
|
2012-07-10 22:31:04 +00:00
|
|
|
#endif
|
2010-09-16 06:09:19 +00:00
|
|
|
exePath = exePath.DirName();
|
|
|
|
}
|
|
|
|
|
2016-04-08 17:34:40 +00:00
|
|
|
exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
|
2016-10-14 06:55:07 +00:00
|
|
|
|
2019-04-08 20:19:51 +00:00
|
|
|
return pathType;
|
2010-09-16 06:09:19 +00:00
|
|
|
}
|
|
|
|
|
2011-10-14 07:54:46 +00:00
|
|
|
#ifdef MOZ_WIDGET_COCOA
|
2010-09-16 06:09:19 +00:00
|
|
|
class AutoCFTypeObject {
|
|
|
|
public:
|
2014-09-01 01:12:55 +00:00
|
|
|
explicit AutoCFTypeObject(CFTypeRef object) { mObject = object; }
|
2010-09-16 06:09:19 +00:00
|
|
|
~AutoCFTypeObject() { ::CFRelease(mObject); }
|
2018-11-30 10:46:48 +00:00
|
|
|
|
2010-09-16 06:09:19 +00:00
|
|
|
private:
|
|
|
|
CFTypeRef mObject;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2015-04-27 19:09:45 +00:00
|
|
|
// We start the unique IDs at 1 so that 0 can be used to mean that
|
|
|
|
// a component has no unique ID assigned to it.
|
|
|
|
uint32_t GeckoChildProcessHost::sNextUniqueID = 1;
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
uint32_t GeckoChildProcessHost::GetUniqueID() { return sNextUniqueID++; }
|
|
|
|
|
2012-08-07 23:29:32 +00:00
|
|
|
void GeckoChildProcessHost::PrepareLaunch() {
|
|
|
|
if (CrashReporter::GetEnabled()) {
|
|
|
|
CrashReporter::OOPInit();
|
|
|
|
}
|
|
|
|
|
2017-10-06 23:15:46 +00:00
|
|
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
|
|
|
SandboxLaunchPrepare(mProcessType, mLaunchOptions.get());
|
|
|
|
#endif
|
|
|
|
|
2012-08-07 23:29:32 +00:00
|
|
|
#ifdef XP_WIN
|
2014-07-17 15:15:09 +00:00
|
|
|
if (mProcessType == GeckoProcessType_Plugin) {
|
|
|
|
InitWindowsGroupID();
|
2014-05-18 03:05:46 +00:00
|
|
|
}
|
2014-06-11 14:32:37 +00:00
|
|
|
|
2019-03-18 22:31:59 +00:00
|
|
|
# if defined(MOZ_SANDBOX)
|
2014-06-11 14:32:37 +00:00
|
|
|
// We need to get the pref here as the process is launched off main thread.
|
|
|
|
if (mProcessType == GeckoProcessType_Content) {
|
2017-05-12 21:04:42 +00:00
|
|
|
mSandboxLevel = GetEffectiveContentSandboxLevel();
|
2014-11-29 17:12:18 +00:00
|
|
|
mEnableSandboxLogging =
|
2017-01-23 20:46:49 +00:00
|
|
|
Preferences::GetBool("security.sandbox.logging.enabled");
|
2017-08-07 16:42:00 +00:00
|
|
|
|
|
|
|
// We currently have to whitelist certain paths for tests to work in some
|
|
|
|
// development configurations.
|
|
|
|
nsAutoString readPaths;
|
|
|
|
nsresult rv = Preferences::GetString(
|
|
|
|
"security.sandbox.content.read_path_whitelist", readPaths);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
for (const nsAString& readPath : readPaths.Split(',')) {
|
|
|
|
nsString trimmedPath(readPath);
|
|
|
|
trimmedPath.Trim(" ", true, true);
|
|
|
|
std::wstring resolvedPath(trimmedPath.Data());
|
|
|
|
// Before resolving check if path ends with '\' as this indicates we
|
|
|
|
// want to give read access to a directory and so it needs a wildcard.
|
|
|
|
bool addWildcard = (resolvedPath.back() == L'\\');
|
|
|
|
if (!widget::WinUtils::ResolveJunctionPointsAndSymLinks(resolvedPath)) {
|
|
|
|
NS_ERROR("Failed to resolve test read policy rule.");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addWildcard) {
|
|
|
|
resolvedPath.append(L"\\*");
|
|
|
|
}
|
|
|
|
mAllowedFilesRead.push_back(resolvedPath);
|
|
|
|
}
|
|
|
|
}
|
2014-06-11 14:32:37 +00:00
|
|
|
}
|
|
|
|
# endif
|
2014-11-29 17:12:18 +00:00
|
|
|
|
|
|
|
# if defined(MOZ_SANDBOX)
|
|
|
|
// For other process types we can't rely on them being launched on main
|
|
|
|
// thread and they may not have access to prefs in the child process, so allow
|
|
|
|
// them to turn on logging via an environment variable.
|
|
|
|
mEnableSandboxLogging =
|
2017-01-23 20:46:49 +00:00
|
|
|
mEnableSandboxLogging || !!PR_GetEnv("MOZ_SANDBOX_LOGGING");
|
2014-11-29 17:12:18 +00:00
|
|
|
# endif
|
2018-01-09 15:29:40 +00:00
|
|
|
#elif defined(XP_LINUX)
|
2019-03-18 22:31:59 +00:00
|
|
|
# if defined(MOZ_SANDBOX)
|
2018-01-09 15:29:40 +00:00
|
|
|
// Get and remember the path to the per-content-process tmpdir
|
|
|
|
if (ShouldHaveDirectoryService()) {
|
|
|
|
nsCOMPtr<nsIFile> contentTempDir;
|
|
|
|
nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
2018-01-09 16:51:55 +00:00
|
|
|
getter_AddRefs(contentTempDir));
|
2018-01-09 15:29:40 +00:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
contentTempDir->GetNativePath(mTmpDirName);
|
|
|
|
}
|
|
|
|
}
|
2018-01-09 16:51:55 +00:00
|
|
|
# endif
|
2018-01-09 16:51:55 +00:00
|
|
|
#endif
|
2012-08-07 23:29:32 +00:00
|
|
|
}
|
|
|
|
|
2010-07-01 03:07:50 +00:00
|
|
|
#ifdef XP_WIN
|
|
|
|
void GeckoChildProcessHost::InitWindowsGroupID() {
|
|
|
|
// On Win7+, pass the application user model to the child, so it can
|
|
|
|
// register with it. This insures windows created by the container
|
|
|
|
// properly group with the parent app on the Win7 taskbar.
|
|
|
|
nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
|
|
|
|
if (taskbarInfo) {
|
2011-09-29 06:19:26 +00:00
|
|
|
bool isSupported = false;
|
2010-07-01 03:07:50 +00:00
|
|
|
taskbarInfo->GetAvailable(&isSupported);
|
|
|
|
nsAutoString appId;
|
|
|
|
if (isSupported && NS_SUCCEEDED(taskbarInfo->GetDefaultGroupId(appId))) {
|
Bug 1447246 - Refactor ContentProcess::Init(). r=jimm
The current code is a bit of a mess. This patch does the following.
- Changes the processing from backwards to forwards. This avoids the need for
all the `found` booleans, because if a flag is present multiple times, the
last one will naturally override.
- Tightens up the checking. It now doesn't use assertions, but instead returns
false if any of the options are missing arguments, or have malformed
arguments, or any of the mandatory flags are missing. (It assumes that
-appdir and -profile are optional.)
- Renames the loop variable `idx` as `i`.
- Changes `!strcmp(...)` to `strcmp(...) == 0`, because I find that clearer.
- Avoids a redundant nsCString when handling -appdir.
The patch also tweaks GeckoChildProcessHost::mGroupId, which was buggy. It
holds the appModelUserId argument, which XRE_InitChildProcess() always expects
is present in the command. But it's only set to a non-empty value in
InitWindowsGroupID(), which is only called for plugin processes. So in lots of
cases the appModelUserId argument was missing, and a different argument would
be interpreted as the appModelUserId argument (seemingly without noticeable ill
effect).
The patch changes things to mGroupId defaults to "-", which means it's always
present in the command.
Note: all this explains why the old code for ContentProcess::Init() started
processing from argument aArgc, instead of aArgc-1 as you might expect -- it
had to read one extra arg in order to see the argument following -appdir,
because XRE_InitChildProcess() was decrementing aArgc for the appModelUserId
argument even when that argument wasn't present. The new code for
ContentProcess::Init() doesn't have to read past aArgc-1 because the mGroupId
fix ensures the appModelUserId argument is always present.
MozReview-Commit-ID: 8a8k6ABYMgo
--HG--
extra : rebase_source : 70695125ee26e67af3337119f4dfc293a0dab74c
2018-03-16 01:23:10 +00:00
|
|
|
MOZ_ASSERT(mGroupId.EqualsLiteral("-"));
|
|
|
|
mGroupId.Assign(appId);
|
2010-07-01 03:07:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-10-05 02:31:12 +00:00
|
|
|
bool GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts,
|
|
|
|
int aTimeoutMs) {
|
2018-09-14 17:26:49 +00:00
|
|
|
if (!AsyncLaunch(std::move(aExtraOpts))) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-12-29 23:13:28 +00:00
|
|
|
return WaitUntilConnected(aTimeoutMs);
|
|
|
|
}
|
|
|
|
|
2017-10-05 02:31:12 +00:00
|
|
|
bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) {
|
2014-12-29 23:13:28 +00:00
|
|
|
PrepareLaunch();
|
|
|
|
|
2019-03-28 02:25:52 +00:00
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
|
|
if (IsMacSandboxLaunchEnabled()) {
|
|
|
|
AppendMacSandboxParams(aExtraOpts);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-12-29 23:13:28 +00:00
|
|
|
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
|
2016-05-05 08:44:59 +00:00
|
|
|
|
2018-11-28 20:42:31 +00:00
|
|
|
MOZ_ASSERT(mHandlePromise == nullptr);
|
|
|
|
mHandlePromise = new HandlePromise::Private(__func__);
|
|
|
|
|
2018-09-14 17:26:49 +00:00
|
|
|
// Currently this can't fail (see the MOZ_ALWAYS_SUCCEEDS in
|
|
|
|
// MessageLoop::PostTask_Helper), but in the future it possibly
|
|
|
|
// could, in which case this method could return false.
|
2017-10-05 02:31:12 +00:00
|
|
|
ioLoop->PostTask(NewNonOwningRunnableMethod<std::vector<std::string>>(
|
2017-06-12 19:34:10 +00:00
|
|
|
"ipc::GeckoChildProcessHost::RunPerformAsyncLaunch", this,
|
|
|
|
&GeckoChildProcessHost::RunPerformAsyncLaunch, aExtraOpts));
|
2014-12-29 23:13:28 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GeckoChildProcessHost::WaitUntilConnected(int32_t aTimeoutMs) {
|
Bug 1375392 - Tweak the PROFILER_LABEL* macros. r=mstange.
This patch makes the following changes to the macros.
- Removes PROFILER_LABEL_FUNC. It's only suitable for use in functions outside
classes, due to PROFILER_FUNCTION_NAME not getting class names, and it was
mostly misused.
- Removes PROFILER_FUNCTION_NAME. It's no longer used, and __func__ is
universally available now anyway.
- Combines the first two string literal arguments of PROFILER_LABEL and
PROFILER_LABEL_DYNAMIC into a single argument. There was no good reason for
them to be separate, and it forced a '::' in the label, which isn't always
appropriate. Also, the meaning of the "name_space" argument was interpreted
in an interesting variety of ways.
- Adds an "AUTO_" prefix to PROFILER_LABEL and PROFILER_LABEL_DYNAMIC, to make
it clearer they construct RAII objects rather than just being function calls.
(I myself have screwed up the scoping because of this in the past.)
- Fills in the 'js::ProfileEntry::Category::' qualifier within the macro, so
the caller doesn't need to. This makes a *lot* more of the uses fit onto a
single line.
The patch also makes the following changes to the macro uses (beyond those
required by the changes described above).
- Fixes a bunch of labels that had gotten out of sync with the name of the
class and/or function that encloses them.
- Removes a useless PROFILER_LABEL use within a trivial scope in
EventStateManager::DispatchMouseOrPointerEvent(). It clearly wasn't serving
any useful purpose. It also serves as extra evidence that the AUTO_ prefix is
a good idea.
- Tweaks DecodePool::SyncRunIf{Preferred,Possible} so that the labelling is
done within them, instead of at their callsites, because that's a more
standard way of doing things.
--HG--
extra : rebase_source : 318d1bc6fc1425a94aacbf489dd46e4f83211de4
2017-06-22 07:08:53 +00:00
|
|
|
AUTO_PROFILER_LABEL("GeckoChildProcessHost::WaitUntilConnected", OTHER);
|
2016-01-15 10:38:03 +00:00
|
|
|
|
2009-07-20 18:14:41 +00:00
|
|
|
// NB: this uses a different mechanism than the chromium parent
|
|
|
|
// class.
|
2018-02-09 20:17:26 +00:00
|
|
|
TimeDuration timeout = (aTimeoutMs > 0)
|
|
|
|
? TimeDuration::FromMilliseconds(aTimeoutMs)
|
|
|
|
: TimeDuration::Forever();
|
2014-12-29 23:13:28 +00:00
|
|
|
|
2011-04-29 19:21:57 +00:00
|
|
|
MonitorAutoLock lock(mMonitor);
|
2018-02-09 20:17:26 +00:00
|
|
|
TimeStamp waitStart = TimeStamp::Now();
|
|
|
|
TimeStamp current;
|
2010-08-10 21:14:10 +00:00
|
|
|
|
|
|
|
// We'll receive several notifications, we need to exit when we
|
|
|
|
// have either successfully launched or have timed out.
|
2014-01-12 03:51:00 +00:00
|
|
|
while (mProcessState != PROCESS_CONNECTED) {
|
|
|
|
// If there was an error then return it, don't wait out the timeout.
|
|
|
|
if (mProcessState == PROCESS_ERROR) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-02-09 20:17:26 +00:00
|
|
|
CVStatus status = lock.Wait(timeout);
|
|
|
|
if (status == CVStatus::Timeout) {
|
|
|
|
break;
|
|
|
|
}
|
2010-08-10 21:14:10 +00:00
|
|
|
|
2018-02-09 20:17:26 +00:00
|
|
|
if (timeout != TimeDuration::Forever()) {
|
|
|
|
current = TimeStamp::Now();
|
|
|
|
timeout -= current - waitStart;
|
2010-08-10 21:14:10 +00:00
|
|
|
waitStart = current;
|
|
|
|
}
|
2009-07-20 18:14:41 +00:00
|
|
|
}
|
|
|
|
|
2012-08-07 23:29:32 +00:00
|
|
|
return mProcessState == PROCESS_CONNECTED;
|
2009-06-29 18:38:29 +00:00
|
|
|
}
|
|
|
|
|
2012-08-07 23:29:32 +00:00
|
|
|
bool GeckoChildProcessHost::LaunchAndWaitForProcessHandle(
|
|
|
|
StringVector aExtraOpts) {
|
2018-09-14 17:26:49 +00:00
|
|
|
if (!AsyncLaunch(std::move(aExtraOpts))) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-07 23:29:32 +00:00
|
|
|
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
while (mProcessState < PROCESS_CREATED) {
|
|
|
|
lock.Wait();
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(mProcessState == PROCESS_ERROR || mChildProcessHandle);
|
|
|
|
|
|
|
|
return mProcessState < PROCESS_ERROR;
|
|
|
|
}
|
|
|
|
|
2009-11-18 21:43:53 +00:00
|
|
|
void GeckoChildProcessHost::InitializeChannel() {
|
|
|
|
CreateChannel();
|
|
|
|
|
2011-04-29 19:21:57 +00:00
|
|
|
MonitorAutoLock lock(mMonitor);
|
2012-08-07 23:29:32 +00:00
|
|
|
mProcessState = CHANNEL_INITIALIZED;
|
2011-04-29 19:21:57 +00:00
|
|
|
lock.Notify();
|
2009-11-18 21:43:53 +00:00
|
|
|
}
|
|
|
|
|
2012-12-28 09:45:16 +00:00
|
|
|
void GeckoChildProcessHost::Join() {
|
|
|
|
AssertIOThread();
|
|
|
|
|
|
|
|
if (!mChildProcessHandle) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this fails, there's nothing we can do.
|
|
|
|
base::KillProcess(mChildProcessHandle, 0, /*wait*/ true);
|
2014-03-21 12:50:07 +00:00
|
|
|
SetAlreadyDead();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GeckoChildProcessHost::SetAlreadyDead() {
|
2015-04-01 08:40:35 +00:00
|
|
|
if (mChildProcessHandle && mChildProcessHandle != kInvalidProcessHandle) {
|
|
|
|
base::CloseProcessHandle(mChildProcessHandle);
|
|
|
|
}
|
|
|
|
|
2012-12-28 09:45:16 +00:00
|
|
|
mChildProcessHandle = 0;
|
|
|
|
}
|
|
|
|
|
2012-08-22 15:56:38 +00:00
|
|
|
int32_t GeckoChildProcessHost::mChildCounter = 0;
|
2011-03-25 23:40:50 +00:00
|
|
|
|
2018-01-08 09:07:16 +00:00
|
|
|
void GeckoChildProcessHost::GetChildLogName(const char* origLogName,
|
2016-05-26 07:18:00 +00:00
|
|
|
nsACString& buffer) {
|
2017-03-06 16:42:31 +00:00
|
|
|
#ifdef XP_WIN
|
|
|
|
// On Windows we must expand relative paths because sandboxing rules
|
|
|
|
// bound only to full paths. fopen fowards to NtCreateFile which checks
|
|
|
|
// the path against the sanboxing rules as passed to fopen (left relative).
|
|
|
|
char absPath[MAX_PATH + 2];
|
|
|
|
if (_fullpath(absPath, origLogName, sizeof(absPath))) {
|
2017-06-23 15:29:15 +00:00
|
|
|
# ifdef MOZ_SANDBOX
|
|
|
|
// We need to make sure the child log name doesn't contain any junction
|
|
|
|
// points or symlinks or the sandbox will reject rules to allow writing.
|
|
|
|
std::wstring resolvedPath(NS_ConvertUTF8toUTF16(absPath).get());
|
|
|
|
if (widget::WinUtils::ResolveJunctionPointsAndSymLinks(resolvedPath)) {
|
2018-07-06 07:44:43 +00:00
|
|
|
AppendUTF16toUTF8(
|
|
|
|
MakeSpan(reinterpret_cast<const char16_t*>(resolvedPath.data()),
|
|
|
|
resolvedPath.size()),
|
|
|
|
buffer);
|
2017-06-23 15:29:15 +00:00
|
|
|
} else
|
|
|
|
# endif
|
|
|
|
{
|
|
|
|
buffer.Append(absPath);
|
|
|
|
}
|
2017-03-06 16:42:31 +00:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
buffer.Append(origLogName);
|
|
|
|
}
|
2011-03-25 23:40:50 +00:00
|
|
|
|
|
|
|
// Append child-specific postfix to name
|
2016-05-26 07:18:00 +00:00
|
|
|
buffer.AppendLiteral(".child-");
|
|
|
|
buffer.AppendInt(mChildCounter);
|
2017-11-03 19:28:00 +00:00
|
|
|
}
|
2017-10-12 09:18:25 +00:00
|
|
|
|
2019-02-05 00:15:22 +00:00
|
|
|
namespace {
|
|
|
|
// Windows needs a single dedicated thread for process launching,
|
|
|
|
// because of thread-safety restrictions/assertions in the sandbox
|
|
|
|
// code. (This implementation isn't itself Windows-specific, so
|
|
|
|
// the ifdef can be changed to test on other platforms.)
|
|
|
|
#ifdef XP_WIN
|
|
|
|
|
|
|
|
static mozilla::StaticMutex gIPCLaunchThreadMutex;
|
|
|
|
static mozilla::StaticRefPtr<nsIThread> gIPCLaunchThread;
|
|
|
|
|
|
|
|
class IPCLaunchThreadObserver final : public nsIObserver {
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
protected:
|
|
|
|
virtual ~IPCLaunchThreadObserver() = default;
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS(IPCLaunchThreadObserver, nsIObserver, nsISupports)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
IPCLaunchThreadObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|
|
|
const char16_t* aData) {
|
|
|
|
MOZ_RELEASE_ASSERT(strcmp(aTopic, "xpcom-shutdown-threads") == 0);
|
|
|
|
StaticMutexAutoLock lock(gIPCLaunchThreadMutex);
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
if (gIPCLaunchThread) {
|
|
|
|
rv = gIPCLaunchThread->Shutdown();
|
|
|
|
gIPCLaunchThread = nullptr;
|
|
|
|
}
|
|
|
|
mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsCOMPtr<nsIEventTarget> GetIPCLauncher() {
|
|
|
|
StaticMutexAutoLock lock(gIPCLaunchThreadMutex);
|
|
|
|
if (!gIPCLaunchThread) {
|
|
|
|
nsCOMPtr<nsIThread> thread;
|
|
|
|
nsresult rv = NS_NewNamedThread(NS_LITERAL_CSTRING("IPC Launch"),
|
|
|
|
getter_AddRefs(thread));
|
|
|
|
if (!NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
NS_DispatchToMainThread(
|
|
|
|
NS_NewRunnableFunction("GeckoChildProcessHost::GetIPCLauncher", [] {
|
|
|
|
nsCOMPtr<nsIObserverService> obsService =
|
|
|
|
mozilla::services::GetObserverService();
|
|
|
|
nsCOMPtr<nsIObserver> obs = new IPCLaunchThreadObserver();
|
|
|
|
obsService->AddObserver(obs, "xpcom-shutdown-threads", false);
|
|
|
|
}));
|
|
|
|
gIPCLaunchThread = thread.forget();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIEventTarget> thread = gIPCLaunchThread.get();
|
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
#else // XP_WIN
|
2019-01-10 20:55:31 +00:00
|
|
|
|
2019-02-05 00:15:22 +00:00
|
|
|
// Non-Windows platforms can use an on-demand thread pool.
|
|
|
|
|
|
|
|
static nsCOMPtr<nsIEventTarget> GetIPCLauncher() {
|
|
|
|
nsCOMPtr<nsIEventTarget> pool =
|
|
|
|
mozilla::SharedThreadPool::Get(NS_LITERAL_CSTRING("IPC Launch"));
|
|
|
|
return pool;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // XP_WIN
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
void GeckoChildProcessHost::RunPerformAsyncLaunch(
|
|
|
|
std::vector<std::string> aExtraOpts) {
|
|
|
|
// Warning: rejecting the promise allows `this` to be deleted. Do
|
|
|
|
// not use `this` after calling the `fail` function (including
|
|
|
|
// destructors of AutoLock objects).
|
|
|
|
//
|
|
|
|
// (Deletion happens on the I/O thread, so it's safe to access
|
|
|
|
// `this` afterwards from RunPerformAsyncLaunch itself, but not from
|
|
|
|
// the launchWrapper closure. For simplicity, it's just treated
|
|
|
|
// like `delete this` everywhere.)
|
|
|
|
auto fail = [this] {
|
2019-02-05 00:15:20 +00:00
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
mProcessState = PROCESS_ERROR;
|
|
|
|
lock.Notify();
|
|
|
|
}
|
|
|
|
mHandlePromise->Reject(LaunchError{}, __func__);
|
2019-02-05 00:15:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// This (probably?) needs to happen on the I/O thread.
|
|
|
|
InitializeChannel();
|
|
|
|
|
|
|
|
// But the rest of this doesn't, and shouldn't block IPC messages:
|
|
|
|
auto launchWrapper = [this, fail, aExtraOpts = std::move(aExtraOpts)]() {
|
|
|
|
bool ok = PerformAsyncLaunch(aExtraOpts);
|
|
|
|
|
|
|
|
if (!ok) {
|
|
|
|
// WaitUntilConnected might be waiting for us to signal.
|
|
|
|
// If something failed let's set the error state and notify.
|
|
|
|
CHROMIUM_LOG(ERROR) << "Failed to launch "
|
|
|
|
<< XRE_ChildProcessTypeToString(mProcessType)
|
|
|
|
<< " subprocess";
|
|
|
|
Telemetry::Accumulate(
|
|
|
|
Telemetry::SUBPROCESS_LAUNCH_FAILURE,
|
|
|
|
nsDependentCString(XRE_ChildProcessTypeToString(mProcessType)));
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// The Web Replay middleman process launches the actual content
|
|
|
|
// processes, and doesn't initialize enough of XPCOM to use thread
|
|
|
|
// pools.
|
|
|
|
if (!mozilla::recordreplay::IsMiddleman()) {
|
|
|
|
auto launcher = GetIPCLauncher();
|
|
|
|
MOZ_DIAGNOSTIC_ASSERT(launcher != nullptr);
|
|
|
|
// Creating a thread pool shouldn't normally fail, but in case it
|
|
|
|
// does, use the fallback we already have for the middleman case.
|
|
|
|
if (launcher != nullptr) {
|
|
|
|
nsresult rv = launcher->Dispatch(
|
|
|
|
NS_NewRunnableFunction(
|
|
|
|
"ipc::GeckoChildProcessHost::PerformAsyncLaunch", launchWrapper),
|
|
|
|
NS_DISPATCH_NORMAL);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
CHROMIUM_LOG(ERROR) << "Failed to dispatch launch task for "
|
|
|
|
<< XRE_ChildProcessTypeToString(mProcessType)
|
|
|
|
<< " process; launching during shutdown?";
|
|
|
|
fail();
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2016-06-01 22:13:59 +00:00
|
|
|
}
|
2019-02-05 00:15:22 +00:00
|
|
|
|
|
|
|
// Fall back to launching on the I/O thread.
|
|
|
|
launchWrapper();
|
2013-05-31 13:16:54 +00:00
|
|
|
}
|
|
|
|
|
2012-12-18 16:24:42 +00:00
|
|
|
void
|
|
|
|
#if defined(XP_WIN)
|
|
|
|
AddAppDirToCommandLine(CommandLine& aCmdLine)
|
|
|
|
#else
|
|
|
|
AddAppDirToCommandLine(std::vector<std::string>& aCmdLine)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// Content processes need access to application resources, so pass
|
|
|
|
// the full application directory path to the child process.
|
|
|
|
if (ShouldHaveDirectoryService()) {
|
|
|
|
nsCOMPtr<nsIProperties> directoryService(
|
|
|
|
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
|
|
|
|
NS_ASSERTION(directoryService, "Expected XPCOM to be available");
|
|
|
|
if (directoryService) {
|
|
|
|
nsCOMPtr<nsIFile> appDir;
|
|
|
|
// NS_XPCOM_CURRENT_PROCESS_DIR really means the app dir, not the
|
|
|
|
// current process dir.
|
|
|
|
nsresult rv =
|
|
|
|
directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
|
|
|
|
NS_GET_IID(nsIFile), getter_AddRefs(appDir));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
#if defined(XP_WIN)
|
2015-11-23 23:27:23 +00:00
|
|
|
nsString path;
|
2016-03-28 17:28:15 +00:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(appDir->GetPath(path));
|
2012-12-18 16:24:42 +00:00
|
|
|
aCmdLine.AppendLooseValue(UTF8ToWide("-appdir"));
|
2015-12-01 13:20:41 +00:00
|
|
|
std::wstring wpath(path.get());
|
2015-11-23 23:27:23 +00:00
|
|
|
aCmdLine.AppendLooseValue(wpath);
|
2012-12-18 16:24:42 +00:00
|
|
|
#else
|
2015-11-23 23:27:23 +00:00
|
|
|
nsAutoCString path;
|
2016-03-28 17:28:15 +00:00
|
|
|
MOZ_ALWAYS_SUCCEEDS(appDir->GetNativePath(path));
|
2012-12-18 16:24:42 +00:00
|
|
|
aCmdLine.push_back("-appdir");
|
|
|
|
aCmdLine.push_back(path.get());
|
|
|
|
#endif
|
|
|
|
}
|
2016-08-30 20:32:21 +00:00
|
|
|
|
2019-03-18 22:31:59 +00:00
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
2016-08-30 20:32:21 +00:00
|
|
|
// Full path to the profile dir
|
|
|
|
nsCOMPtr<nsIFile> profileDir;
|
|
|
|
rv =
|
|
|
|
directoryService->Get(NS_APP_USER_PROFILE_50_DIR, NS_GET_IID(nsIFile),
|
|
|
|
getter_AddRefs(profileDir));
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2018-10-19 18:23:16 +00:00
|
|
|
// If the profile doesn't exist, normalization will
|
|
|
|
// fail. But we don't return an error here because some
|
|
|
|
// tests require startup with a missing profile dir.
|
|
|
|
// For users, almost universally, the profile will be in
|
|
|
|
// the home directory and normalization isn't required.
|
|
|
|
mozilla::Unused << profileDir->Normalize();
|
2016-08-30 20:32:21 +00:00
|
|
|
nsAutoCString path;
|
|
|
|
MOZ_ALWAYS_SUCCEEDS(profileDir->GetNativePath(path));
|
|
|
|
aCmdLine.push_back("-profile");
|
|
|
|
aCmdLine.push_back(path.get());
|
|
|
|
}
|
|
|
|
#endif
|
2012-12-18 16:24:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-01 19:29:39 +00:00
|
|
|
#if defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
|
2019-02-12 02:45:07 +00:00
|
|
|
static bool Contains(const std::vector<std::string>& aExtraOpts,
|
|
|
|
const char* aValue) {
|
|
|
|
return std::any_of(aExtraOpts.begin(), aExtraOpts.end(),
|
|
|
|
[&](const std::string arg) {
|
|
|
|
return arg.find(aValue) != std::string::npos;
|
|
|
|
});
|
|
|
|
}
|
2019-03-01 19:29:39 +00:00
|
|
|
#endif // defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
|
2019-02-12 02:45:07 +00:00
|
|
|
|
2018-09-14 17:28:38 +00:00
|
|
|
bool GeckoChildProcessHost::PerformAsyncLaunch(
|
|
|
|
std::vector<std::string> aExtraOpts) {
|
|
|
|
#ifdef MOZ_GECKO_PROFILER
|
2019-01-08 23:53:36 +00:00
|
|
|
GetProfilerEnvVarsForChildProcess([this](const char* key, const char* value) {
|
|
|
|
mLaunchOptions->env_map[ENVIRONMENT_STRING(key)] =
|
|
|
|
ENVIRONMENT_STRING(value);
|
|
|
|
});
|
2018-09-14 17:28:38 +00:00
|
|
|
#endif
|
|
|
|
|
2018-11-28 20:42:33 +00:00
|
|
|
const auto startTS = TimeStamp::Now();
|
|
|
|
|
2018-09-14 17:28:38 +00:00
|
|
|
// - Note: this code is not called re-entrantly, nor are restoreOrig*LogName
|
|
|
|
// or mChildCounter touched by any other thread, so this is safe.
|
|
|
|
++mChildCounter;
|
|
|
|
|
|
|
|
const char* origNSPRLogName = PR_GetEnv("NSPR_LOG_FILE");
|
|
|
|
const char* origMozLogName = PR_GetEnv("MOZ_LOG_FILE");
|
|
|
|
|
|
|
|
if (origNSPRLogName) {
|
|
|
|
nsAutoCString nsprLogName;
|
|
|
|
GetChildLogName(origNSPRLogName, nsprLogName);
|
|
|
|
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("NSPR_LOG_FILE")] =
|
2019-01-08 23:53:36 +00:00
|
|
|
ENVIRONMENT_STRING(nsprLogName.get());
|
2018-09-14 17:28:38 +00:00
|
|
|
}
|
|
|
|
if (origMozLogName) {
|
|
|
|
nsAutoCString mozLogName;
|
|
|
|
GetChildLogName(origMozLogName, mozLogName);
|
|
|
|
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MOZ_LOG_FILE")] =
|
2019-01-08 23:53:36 +00:00
|
|
|
ENVIRONMENT_STRING(mozLogName.get());
|
2018-09-14 17:28:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// `RUST_LOG_CHILD` is meant for logging child processes only.
|
|
|
|
nsAutoCString childRustLog(PR_GetEnv("RUST_LOG_CHILD"));
|
|
|
|
if (!childRustLog.IsEmpty()) {
|
|
|
|
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("RUST_LOG")] =
|
2019-01-08 23:53:36 +00:00
|
|
|
ENVIRONMENT_STRING(childRustLog.get());
|
2018-09-14 17:28:38 +00:00
|
|
|
}
|
|
|
|
|
2019-03-18 22:31:59 +00:00
|
|
|
#if defined(XP_LINUX) && defined(MOZ_SANDBOX)
|
2018-09-14 17:28:38 +00:00
|
|
|
if (!mTmpDirName.IsEmpty()) {
|
|
|
|
// Point a bunch of things that might want to write from content to our
|
|
|
|
// shiny new content-process specific tmpdir
|
|
|
|
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("TMPDIR")] =
|
2019-01-08 23:53:36 +00:00
|
|
|
ENVIRONMENT_STRING(mTmpDirName.get());
|
2018-09-14 17:28:38 +00:00
|
|
|
// Partial fix for bug 1380051 (not persistent - should be)
|
|
|
|
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MESA_GLSL_CACHE_DIR")] =
|
2019-01-08 23:53:36 +00:00
|
|
|
ENVIRONMENT_STRING(mTmpDirName.get());
|
2018-09-14 17:28:38 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-11-18 21:43:53 +00:00
|
|
|
// We rely on the fact that InitializeChannel() has already been processed
|
|
|
|
// on the IO thread before this point is reached.
|
|
|
|
if (!GetChannel()) {
|
2009-06-29 18:38:29 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-08-09 06:23:24 +00:00
|
|
|
base::ProcessHandle process = 0;
|
2009-11-06 00:24:27 +00:00
|
|
|
|
|
|
|
// send the child the PID so that it can open a ProcessHandle back to us.
|
|
|
|
// probably don't want to do this in the long run
|
|
|
|
char pidstring[32];
|
2017-11-07 13:57:23 +00:00
|
|
|
SprintfLiteral(pidstring, "%d", base::GetCurrentProcId());
|
2009-11-06 00:24:27 +00:00
|
|
|
|
|
|
|
const char* const childProcessType =
|
|
|
|
XRE_ChildProcessTypeToString(mProcessType);
|
2009-06-29 18:38:29 +00:00
|
|
|
|
2018-12-19 15:29:09 +00:00
|
|
|
ScopedPRFileDesc crashAnnotationReadPipe;
|
|
|
|
ScopedPRFileDesc crashAnnotationWritePipe;
|
|
|
|
if (PR_CreatePipe(&crashAnnotationReadPipe.rwget(),
|
|
|
|
&crashAnnotationWritePipe.rwget()) != PR_SUCCESS) {
|
2017-11-27 20:37:34 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-11-06 00:24:27 +00:00
|
|
|
//--------------------------------------------------
|
|
|
|
#if defined(OS_POSIX)
|
|
|
|
// For POSIX, we have to be extremely anal about *not* using
|
|
|
|
// std::wstring in code compiled with Mozilla's -fshort-wchar
|
|
|
|
// configuration, because chromium is compiled with -fno-short-wchar
|
|
|
|
// and passing wstrings from one config to the other is unsafe. So
|
|
|
|
// we split the logic here.
|
|
|
|
|
2018-01-08 09:07:16 +00:00
|
|
|
# if defined(OS_POSIX)
|
2017-09-13 14:17:39 +00:00
|
|
|
# if defined(MOZ_WIDGET_GTK)
|
2016-07-27 01:24:42 +00:00
|
|
|
if (mProcessType == GeckoProcessType_Content) {
|
|
|
|
// disable IM module to avoid sandbox violation
|
2018-01-08 09:07:16 +00:00
|
|
|
mLaunchOptions->env_map["GTK_IM_MODULE"] = "gtk-im-context-simple";
|
2017-05-04 03:51:49 +00:00
|
|
|
|
|
|
|
// Disable ATK accessibility code in content processes because it conflicts
|
|
|
|
// with the sandbox, and we proxy that information through the main process
|
|
|
|
// anyway.
|
2018-01-08 09:07:16 +00:00
|
|
|
mLaunchOptions->env_map["NO_AT_BRIDGE"] = "1";
|
2016-07-27 01:24:42 +00:00
|
|
|
}
|
2017-09-13 14:17:39 +00:00
|
|
|
# endif // defined(MOZ_WIDGET_GTK)
|
2016-07-27 01:24:42 +00:00
|
|
|
|
2011-06-03 18:33:55 +00:00
|
|
|
// XPCOM may not be initialized in some subprocesses. We don't want
|
|
|
|
// to initialize XPCOM just for the directory service, especially
|
|
|
|
// since LD_LIBRARY_PATH is already set correctly in subprocesses
|
|
|
|
// (meaning that we don't need to set that up in the environment).
|
|
|
|
if (ShouldHaveDirectoryService()) {
|
2014-10-10 19:06:57 +00:00
|
|
|
MOZ_ASSERT(gGREBinPath);
|
2014-07-17 15:15:09 +00:00
|
|
|
nsCString path;
|
2014-10-10 19:06:57 +00:00
|
|
|
NS_CopyUnicodeToNative(nsDependentString(gGREBinPath), path);
|
2017-09-13 14:17:39 +00:00
|
|
|
# if defined(OS_LINUX) || defined(OS_BSD)
|
2014-07-17 15:15:09 +00:00
|
|
|
const char* ld_library_path = PR_GetEnv("LD_LIBRARY_PATH");
|
Bug 1187533 - Change how Gtk+2 plugin-container is started on Gtk+3 builds. r=billm
The current situation looks like this: Firefox launches the plugin-container
with two environment variables set:
LD_LIBRARY_PATH=$FIREFOX_DIR:$LD_LIBRARY_PATH
LD_PRELOAD=$FIREFOX_DIR/libmozgtk2.so:$LD_PRELOAD
libxul.so has a dependency on libmozgtk.so (without "2"), but libmozgtk2.so
has a SONAME of libmozgtk.so, so ld.so recognizes libmozgtk2.so as a
dependency of libxul.so, and uses it instead of the actual libmozgtk.so,
making the plugin-container use Gtk+2 instead of Gtk+3 to load Gtk+2 plugins.
Now, ASan sets things up in shared libraries such that they needs a symbol
from the executable binary. So in the case of plugin-container, the
plugin-container executable itself contains some ASan symbols such as
__asan_init_v3. libmozgtk2.so, OTOH, contains an undefined weak reference to
that symbol, like all other Firefox shared libraries.
Since libmozgtk2.so is LD_PRELOADed, it is loaded _before_ the
plugin-container executable, and __asan_init_v3 can't be resolved.
Disabling ASan for libmozgtk2.so would be a possibility, but the build system
doesn't really know how to do that, and filtering out -fsanitize=address
can be fragile.
The alternative possibility, implemented here, is to change the library
loading strategy, renaming libmozgtk2.so to gtk2/libmozgtk.so, and setting
the following environment variable when Firefox launches the plugin-container:
LD_LIBRARY_PATH=$FIREFOX_DIR/gtk2:$FIREFOX_DIR:$LD_LIBRARY_PATH
2015-07-26 05:05:29 +00:00
|
|
|
nsCString new_ld_lib_path(path.get());
|
2014-05-01 11:37:48 +00:00
|
|
|
|
2018-01-09 10:51:07 +00:00
|
|
|
# ifdef MOZ_WIDGET_GTK
|
2014-07-17 15:15:09 +00:00
|
|
|
if (mProcessType == GeckoProcessType_Plugin) {
|
2017-09-04 05:14:11 +00:00
|
|
|
new_ld_lib_path.AppendLiteral("/gtk2:");
|
Bug 1187533 - Change how Gtk+2 plugin-container is started on Gtk+3 builds. r=billm
The current situation looks like this: Firefox launches the plugin-container
with two environment variables set:
LD_LIBRARY_PATH=$FIREFOX_DIR:$LD_LIBRARY_PATH
LD_PRELOAD=$FIREFOX_DIR/libmozgtk2.so:$LD_PRELOAD
libxul.so has a dependency on libmozgtk.so (without "2"), but libmozgtk2.so
has a SONAME of libmozgtk.so, so ld.so recognizes libmozgtk2.so as a
dependency of libxul.so, and uses it instead of the actual libmozgtk.so,
making the plugin-container use Gtk+2 instead of Gtk+3 to load Gtk+2 plugins.
Now, ASan sets things up in shared libraries such that they needs a symbol
from the executable binary. So in the case of plugin-container, the
plugin-container executable itself contains some ASan symbols such as
__asan_init_v3. libmozgtk2.so, OTOH, contains an undefined weak reference to
that symbol, like all other Firefox shared libraries.
Since libmozgtk2.so is LD_PRELOADed, it is loaded _before_ the
plugin-container executable, and __asan_init_v3 can't be resolved.
Disabling ASan for libmozgtk2.so would be a possibility, but the build system
doesn't really know how to do that, and filtering out -fsanitize=address
can be fragile.
The alternative possibility, implemented here, is to change the library
loading strategy, renaming libmozgtk2.so to gtk2/libmozgtk.so, and setting
the following environment variable when Firefox launches the plugin-container:
LD_LIBRARY_PATH=$FIREFOX_DIR/gtk2:$FIREFOX_DIR:$LD_LIBRARY_PATH
2015-07-26 05:05:29 +00:00
|
|
|
new_ld_lib_path.Append(path.get());
|
2014-07-17 15:15:09 +00:00
|
|
|
}
|
2018-01-09 10:51:07 +00:00
|
|
|
# endif // MOZ_WIDGET_GTK
|
Bug 1187533 - Change how Gtk+2 plugin-container is started on Gtk+3 builds. r=billm
The current situation looks like this: Firefox launches the plugin-container
with two environment variables set:
LD_LIBRARY_PATH=$FIREFOX_DIR:$LD_LIBRARY_PATH
LD_PRELOAD=$FIREFOX_DIR/libmozgtk2.so:$LD_PRELOAD
libxul.so has a dependency on libmozgtk.so (without "2"), but libmozgtk2.so
has a SONAME of libmozgtk.so, so ld.so recognizes libmozgtk2.so as a
dependency of libxul.so, and uses it instead of the actual libmozgtk.so,
making the plugin-container use Gtk+2 instead of Gtk+3 to load Gtk+2 plugins.
Now, ASan sets things up in shared libraries such that they needs a symbol
from the executable binary. So in the case of plugin-container, the
plugin-container executable itself contains some ASan symbols such as
__asan_init_v3. libmozgtk2.so, OTOH, contains an undefined weak reference to
that symbol, like all other Firefox shared libraries.
Since libmozgtk2.so is LD_PRELOADed, it is loaded _before_ the
plugin-container executable, and __asan_init_v3 can't be resolved.
Disabling ASan for libmozgtk2.so would be a possibility, but the build system
doesn't really know how to do that, and filtering out -fsanitize=address
can be fragile.
The alternative possibility, implemented here, is to change the library
loading strategy, renaming libmozgtk2.so to gtk2/libmozgtk.so, and setting
the following environment variable when Firefox launches the plugin-container:
LD_LIBRARY_PATH=$FIREFOX_DIR/gtk2:$FIREFOX_DIR:$LD_LIBRARY_PATH
2015-07-26 05:05:29 +00:00
|
|
|
if (ld_library_path && *ld_library_path) {
|
|
|
|
new_ld_lib_path.Append(':');
|
|
|
|
new_ld_lib_path.Append(ld_library_path);
|
|
|
|
}
|
2018-01-08 09:07:16 +00:00
|
|
|
mLaunchOptions->env_map["LD_LIBRARY_PATH"] = new_ld_lib_path.get();
|
2014-05-01 11:37:48 +00:00
|
|
|
|
2017-09-13 14:17:39 +00:00
|
|
|
# elif OS_MACOSX // defined(OS_LINUX) || defined(OS_BSD)
|
2018-01-08 09:07:16 +00:00
|
|
|
mLaunchOptions->env_map["DYLD_LIBRARY_PATH"] = path.get();
|
2014-07-17 15:15:09 +00:00
|
|
|
// XXX DYLD_INSERT_LIBRARIES should only be set when launching a plugin
|
|
|
|
// process, and has no effect on other subprocesses (the hooks in
|
|
|
|
// libplugin_child_interpose.dylib become noops). But currently it
|
|
|
|
// gets set when launching any kind of subprocess.
|
|
|
|
//
|
|
|
|
// Trigger "dyld interposing" for the dylib that contains
|
|
|
|
// plugin_child_interpose.mm. This allows us to hook OS calls in the
|
|
|
|
// plugin process (ones that don't work correctly in a background
|
|
|
|
// process). Don't break any other "dyld interposing" that has already
|
|
|
|
// been set up by whatever may have launched the browser.
|
|
|
|
const char* prevInterpose = PR_GetEnv("DYLD_INSERT_LIBRARIES");
|
|
|
|
nsCString interpose;
|
2015-06-10 16:54:52 +00:00
|
|
|
if (prevInterpose && strlen(prevInterpose) > 0) {
|
2014-07-17 15:15:09 +00:00
|
|
|
interpose.Assign(prevInterpose);
|
|
|
|
interpose.Append(':');
|
2011-05-24 06:58:28 +00:00
|
|
|
}
|
2014-07-17 15:15:09 +00:00
|
|
|
interpose.Append(path.get());
|
|
|
|
interpose.AppendLiteral("/libplugin_child_interpose.dylib");
|
2018-01-08 09:07:16 +00:00
|
|
|
mLaunchOptions->env_map["DYLD_INSERT_LIBRARIES"] = interpose.get();
|
2017-09-13 14:17:39 +00:00
|
|
|
# endif // defined(OS_LINUX) || defined(OS_BSD)
|
2010-03-15 17:08:27 +00:00
|
|
|
}
|
2018-01-08 09:07:16 +00:00
|
|
|
# endif // defined(OS_POSIX)
|
2010-07-19 22:35:45 +00:00
|
|
|
|
2010-09-16 06:09:19 +00:00
|
|
|
FilePath exePath;
|
2019-04-08 20:19:51 +00:00
|
|
|
BinPathType pathType = GetPathToBinary(exePath, mProcessType);
|
2009-06-29 18:38:29 +00:00
|
|
|
|
2009-07-10 19:03:09 +00:00
|
|
|
// remap the IPC socket fd to a well-known int, as the OS does for
|
|
|
|
// STDOUT_FILENO, for example
|
2009-06-29 18:38:29 +00:00
|
|
|
int srcChannelFd, dstChannelFd;
|
|
|
|
channel().GetClientFileDescriptorMapping(&srcChannelFd, &dstChannelFd);
|
2017-09-09 02:35:06 +00:00
|
|
|
mLaunchOptions->fds_to_remap.push_back(
|
|
|
|
std::pair<int, int>(srcChannelFd, dstChannelFd));
|
2010-01-12 21:14:38 +00:00
|
|
|
|
2009-11-06 00:24:27 +00:00
|
|
|
// no need for kProcessChannelID, the child process inherits the
|
|
|
|
// other end of the socketpair() from us
|
|
|
|
|
|
|
|
std::vector<std::string> childArgv;
|
|
|
|
|
|
|
|
childArgv.push_back(exePath.value());
|
|
|
|
|
2019-04-08 20:19:51 +00:00
|
|
|
if (pathType == BinPathType::Self) {
|
2016-06-03 19:49:39 +00:00
|
|
|
childArgv.push_back("-contentproc");
|
|
|
|
}
|
|
|
|
|
2009-11-06 00:24:27 +00:00
|
|
|
childArgv.insert(childArgv.end(), aExtraOpts.begin(), aExtraOpts.end());
|
|
|
|
|
2019-02-14 21:47:45 +00:00
|
|
|
if (mProcessType != GeckoProcessType_GMPlugin) {
|
|
|
|
if (Omnijar::IsInitialized()) {
|
|
|
|
// Make sure that child processes can find the omnijar
|
|
|
|
// See XRE_InitCommandLine in nsAppRunner.cpp
|
|
|
|
nsAutoCString path;
|
|
|
|
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
|
|
|
|
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
|
|
|
|
childArgv.push_back("-greomni");
|
|
|
|
childArgv.push_back(path.get());
|
|
|
|
}
|
|
|
|
file = Omnijar::GetPath(Omnijar::APP);
|
|
|
|
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
|
|
|
|
childArgv.push_back("-appomni");
|
|
|
|
childArgv.push_back(path.get());
|
|
|
|
}
|
2011-06-03 18:33:55 +00:00
|
|
|
}
|
2019-02-14 21:47:45 +00:00
|
|
|
// Add the application directory path (-appdir path)
|
|
|
|
AddAppDirToCommandLine(childArgv);
|
2010-08-10 22:08:06 +00:00
|
|
|
}
|
|
|
|
|
2009-11-06 00:24:27 +00:00
|
|
|
childArgv.push_back(pidstring);
|
|
|
|
|
2017-10-10 10:06:35 +00:00
|
|
|
if (!CrashReporter::IsDummy()) {
|
|
|
|
# if defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
|
|
|
int childCrashFd, childCrashRemapFd;
|
|
|
|
if (!CrashReporter::CreateNotificationPipeForChild(&childCrashFd,
|
|
|
|
&childCrashRemapFd)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (0 <= childCrashFd) {
|
|
|
|
mLaunchOptions->fds_to_remap.push_back(
|
|
|
|
std::pair<int, int>(childCrashFd, childCrashRemapFd));
|
|
|
|
// "true" == crash reporting enabled
|
|
|
|
childArgv.push_back("true");
|
|
|
|
} else {
|
|
|
|
// "false" == crash reporting disabled
|
|
|
|
childArgv.push_back("false");
|
|
|
|
}
|
2018-11-28 09:16:55 +00:00
|
|
|
# elif defined(MOZ_WIDGET_COCOA) /* defined(OS_LINUX) || defined(OS_BSD) || \
|
|
|
|
defined(OS_SOLARIS) */
|
2017-10-10 10:06:35 +00:00
|
|
|
childArgv.push_back(CrashReporter::GetChildNotificationPipe());
|
|
|
|
# endif // defined(OS_LINUX) || defined(OS_BSD) || defined(OS_SOLARIS)
|
2010-01-12 21:14:38 +00:00
|
|
|
}
|
|
|
|
|
2017-11-27 20:37:34 +00:00
|
|
|
int fd = PR_FileDesc2NativeHandle(crashAnnotationWritePipe);
|
|
|
|
mLaunchOptions->fds_to_remap.push_back(
|
|
|
|
std::make_pair(fd, CrashReporter::GetAnnotationTimeCrashFd()));
|
|
|
|
|
2017-09-13 14:17:39 +00:00
|
|
|
# ifdef MOZ_WIDGET_COCOA
|
2010-09-10 17:09:30 +00:00
|
|
|
// Add a mach port to the command line so the child can communicate its
|
|
|
|
// 'task_t' back to the parent.
|
|
|
|
//
|
|
|
|
// Put a random number into the channel name, so that a compromised renderer
|
|
|
|
// can't pretend being the child that's forked off.
|
|
|
|
std::string mach_connection_name =
|
|
|
|
StringPrintf("org.mozilla.machname.%d",
|
|
|
|
base::RandInt(0, std::numeric_limits<int>::max()));
|
|
|
|
childArgv.push_back(mach_connection_name.c_str());
|
2017-09-13 14:17:39 +00:00
|
|
|
# endif // MOZ_WIDGET_COCOA
|
2010-09-10 17:09:30 +00:00
|
|
|
|
|
|
|
childArgv.push_back(childProcessType);
|
|
|
|
|
2018-06-21 17:05:00 +00:00
|
|
|
# ifdef MOZ_WIDGET_COCOA
|
|
|
|
// Register the listening port before launching the child, to ensure
|
|
|
|
// that it's there when the child tries to look it up.
|
|
|
|
ReceivePort parent_recv_port(mach_connection_name.c_str());
|
|
|
|
# endif // MOZ_WIDGET_COCOA
|
|
|
|
|
2017-09-13 14:17:39 +00:00
|
|
|
# if defined(MOZ_WIDGET_ANDROID)
|
2017-09-09 02:35:06 +00:00
|
|
|
LaunchAndroidService(childProcessType, childArgv,
|
|
|
|
mLaunchOptions->fds_to_remap, &process);
|
2017-09-13 14:17:39 +00:00
|
|
|
# else // goes with defined(MOZ_WIDGET_ANDROID)
|
2019-04-01 21:58:23 +00:00
|
|
|
if (!base::LaunchApp(childArgv, *mLaunchOptions, &process)) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-09-13 14:17:39 +00:00
|
|
|
# endif // defined(MOZ_WIDGET_ANDROID)
|
2010-09-10 17:09:30 +00:00
|
|
|
|
2013-07-09 02:37:33 +00:00
|
|
|
// We're in the parent and the child was launched. Close the child FD in the
|
|
|
|
// parent as soon as possible, which will allow the parent to detect when the
|
|
|
|
// child closes its FD (either due to normal exit or due to crash).
|
|
|
|
GetChannel()->CloseClientFileDescriptor();
|
|
|
|
|
2017-09-13 14:17:39 +00:00
|
|
|
# ifdef MOZ_WIDGET_COCOA
|
2010-09-10 17:09:30 +00:00
|
|
|
// Wait for the child process to send us its 'task_t' data.
|
2010-10-14 19:07:38 +00:00
|
|
|
const int kTimeoutMs = 10000;
|
2010-09-10 17:09:30 +00:00
|
|
|
|
|
|
|
MachReceiveMessage child_message;
|
|
|
|
kern_return_t err =
|
|
|
|
parent_recv_port.WaitForMessage(&child_message, kTimeoutMs);
|
|
|
|
if (err != KERN_SUCCESS) {
|
|
|
|
std::string errString =
|
|
|
|
StringPrintf("0x%x %s", err, mach_error_string(err));
|
2013-12-17 18:26:45 +00:00
|
|
|
CHROMIUM_LOG(ERROR) << "parent WaitForMessage() failed: " << errString;
|
2010-09-10 17:09:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
task_t child_task = child_message.GetTranslatedPort(0);
|
|
|
|
if (child_task == MACH_PORT_NULL) {
|
2013-12-17 18:26:45 +00:00
|
|
|
CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(0) failed.";
|
2010-09-10 17:09:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (child_message.GetTranslatedPort(1) == MACH_PORT_NULL) {
|
2013-12-17 18:26:45 +00:00
|
|
|
CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(1) failed.";
|
2010-09-10 17:09:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
MachPortSender parent_sender(child_message.GetTranslatedPort(1));
|
|
|
|
|
2015-06-17 04:38:38 +00:00
|
|
|
if (child_message.GetTranslatedPort(2) == MACH_PORT_NULL) {
|
|
|
|
CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(2) failed.";
|
|
|
|
}
|
2016-11-17 13:07:35 +00:00
|
|
|
auto* parent_recv_port_memory_ack =
|
|
|
|
new MachPortSender(child_message.GetTranslatedPort(2));
|
2015-06-17 04:38:38 +00:00
|
|
|
|
|
|
|
if (child_message.GetTranslatedPort(3) == MACH_PORT_NULL) {
|
|
|
|
CHROMIUM_LOG(ERROR) << "parent GetTranslatedPort(3) failed.";
|
|
|
|
}
|
2016-11-17 13:07:35 +00:00
|
|
|
auto* parent_send_port_memory =
|
|
|
|
new MachPortSender(child_message.GetTranslatedPort(3));
|
2015-06-17 04:38:38 +00:00
|
|
|
|
2010-09-10 17:09:30 +00:00
|
|
|
MachSendMessage parent_message(/* id= */ 0);
|
2014-09-01 01:12:55 +00:00
|
|
|
if (!parent_message.AddDescriptor(MachMsgPortDescriptor(bootstrap_port))) {
|
2013-12-17 18:26:45 +00:00
|
|
|
CHROMIUM_LOG(ERROR) << "parent AddDescriptor(" << bootstrap_port
|
|
|
|
<< ") failed.";
|
2010-09-10 17:09:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-11-17 13:07:35 +00:00
|
|
|
auto* parent_recv_port_memory = new ReceivePort();
|
2015-06-17 04:38:38 +00:00
|
|
|
if (!parent_message.AddDescriptor(
|
|
|
|
MachMsgPortDescriptor(parent_recv_port_memory->GetPort()))) {
|
|
|
|
CHROMIUM_LOG(ERROR) << "parent AddDescriptor("
|
|
|
|
<< parent_recv_port_memory->GetPort() << ") failed.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-11-17 13:07:35 +00:00
|
|
|
auto* parent_send_port_memory_ack = new ReceivePort();
|
2015-06-17 04:38:38 +00:00
|
|
|
if (!parent_message.AddDescriptor(
|
|
|
|
MachMsgPortDescriptor(parent_send_port_memory_ack->GetPort()))) {
|
|
|
|
CHROMIUM_LOG(ERROR) << "parent AddDescriptor("
|
|
|
|
<< parent_send_port_memory_ack->GetPort()
|
|
|
|
<< ") failed.";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-09-10 17:09:30 +00:00
|
|
|
err = parent_sender.SendMessage(parent_message, kTimeoutMs);
|
|
|
|
if (err != KERN_SUCCESS) {
|
|
|
|
std::string errString =
|
|
|
|
StringPrintf("0x%x %s", err, mach_error_string(err));
|
2013-12-17 18:26:45 +00:00
|
|
|
CHROMIUM_LOG(ERROR) << "parent SendMessage() failed: " << errString;
|
2010-09-10 17:09:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
2015-06-17 04:38:38 +00:00
|
|
|
|
|
|
|
SharedMemoryBasic::SetupMachMemory(
|
|
|
|
process, parent_recv_port_memory, parent_recv_port_memory_ack,
|
|
|
|
parent_send_port_memory, parent_send_port_memory_ack, false);
|
|
|
|
|
2017-09-13 14:17:39 +00:00
|
|
|
# endif // MOZ_WIDGET_COCOA
|
2009-11-06 00:24:27 +00:00
|
|
|
|
|
|
|
//--------------------------------------------------
|
2017-09-13 14:17:39 +00:00
|
|
|
#elif defined(OS_WIN) // defined(OS_POSIX)
|
2009-11-06 00:24:27 +00:00
|
|
|
|
2010-09-16 06:09:19 +00:00
|
|
|
FilePath exePath;
|
2019-04-08 20:19:51 +00:00
|
|
|
BinPathType pathType = GetPathToBinary(exePath, mProcessType);
|
2009-06-29 18:38:29 +00:00
|
|
|
|
2019-03-13 09:24:52 +00:00
|
|
|
# if defined(MOZ_SANDBOX) || defined(_ARM64_)
|
2019-02-12 02:45:07 +00:00
|
|
|
const bool isGMP = mProcessType == GeckoProcessType_GMPlugin;
|
|
|
|
const bool isWidevine = isGMP && Contains(aExtraOpts, "gmp-widevinecdm");
|
2019-03-13 09:24:52 +00:00
|
|
|
# if defined(_ARM64_)
|
2019-02-12 02:45:07 +00:00
|
|
|
const bool isClearKey = isGMP && Contains(aExtraOpts, "gmp-clearkey");
|
2019-03-13 09:24:52 +00:00
|
|
|
const bool isSandboxBroker =
|
|
|
|
mProcessType == GeckoProcessType_RemoteSandboxBroker;
|
|
|
|
if (isClearKey || isWidevine || isSandboxBroker) {
|
|
|
|
// On Windows on ARM64 for ClearKey and Widevine, and for the sandbox
|
|
|
|
// launcher process, we want to run the x86 plugin-container.exe in
|
|
|
|
// the "i686" subdirectory, instead of the aarch64 plugin-container.exe.
|
|
|
|
// So insert "i686" into the exePath.
|
2019-02-12 02:45:07 +00:00
|
|
|
exePath = exePath.DirName().AppendASCII("i686").Append(exePath.BaseName());
|
|
|
|
}
|
2019-03-13 09:24:52 +00:00
|
|
|
# endif // if defined(_ARM64_)
|
|
|
|
# endif // defined(MOZ_SANDBOX) || defined(_ARM64_)
|
2019-02-12 02:45:07 +00:00
|
|
|
|
2009-06-29 18:38:29 +00:00
|
|
|
CommandLine cmdLine(exePath.ToWStringHack());
|
2016-06-03 19:49:39 +00:00
|
|
|
|
2019-04-08 20:19:51 +00:00
|
|
|
if (pathType == BinPathType::Self) {
|
2016-06-03 19:49:39 +00:00
|
|
|
cmdLine.AppendLooseValue(UTF8ToWide("-contentproc"));
|
|
|
|
}
|
|
|
|
|
2009-06-29 18:38:29 +00:00
|
|
|
cmdLine.AppendSwitchWithValue(switches::kProcessChannelID, channel_id());
|
|
|
|
|
2009-11-06 00:24:27 +00:00
|
|
|
for (std::vector<std::string>::iterator it = aExtraOpts.begin();
|
2009-07-10 19:03:09 +00:00
|
|
|
it != aExtraOpts.end(); ++it) {
|
2009-11-06 00:24:27 +00:00
|
|
|
cmdLine.AppendLooseValue(UTF8ToWide(*it));
|
2009-07-10 19:03:09 +00:00
|
|
|
}
|
|
|
|
|
2011-06-03 18:33:55 +00:00
|
|
|
if (Omnijar::IsInitialized()) {
|
|
|
|
// Make sure the child process can find the omnijar
|
|
|
|
// See XRE_InitCommandLine in nsAppRunner.cpp
|
|
|
|
nsAutoString path;
|
|
|
|
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
|
|
|
|
if (file && NS_SUCCEEDED(file->GetPath(path))) {
|
|
|
|
cmdLine.AppendLooseValue(UTF8ToWide("-greomni"));
|
|
|
|
cmdLine.AppendLooseValue(path.get());
|
|
|
|
}
|
|
|
|
file = Omnijar::GetPath(Omnijar::APP);
|
|
|
|
if (file && NS_SUCCEEDED(file->GetPath(path))) {
|
|
|
|
cmdLine.AppendLooseValue(UTF8ToWide("-appomni"));
|
|
|
|
cmdLine.AppendLooseValue(path.get());
|
|
|
|
}
|
2010-08-10 22:08:06 +00:00
|
|
|
}
|
|
|
|
|
2018-01-24 15:48:33 +00:00
|
|
|
# if defined(MOZ_SANDBOX)
|
2019-03-13 09:24:52 +00:00
|
|
|
# if defined(_ARM64_)
|
|
|
|
if (isClearKey || isWidevine)
|
|
|
|
mSandboxBroker = new RemoteSandboxBroker();
|
|
|
|
else
|
|
|
|
# endif // if defined(_ARM64_)
|
|
|
|
mSandboxBroker = new SandboxBroker();
|
|
|
|
|
2014-07-16 23:01:34 +00:00
|
|
|
bool shouldSandboxCurrentProcess = false;
|
2015-01-30 17:48:15 +00:00
|
|
|
|
|
|
|
// XXX: Bug 1124167: We should get rid of the process specific logic for
|
|
|
|
// sandboxing in this class at some point. Unfortunately it will take a bit
|
|
|
|
// of reorganizing so I don't think this patch is the right time.
|
2014-07-16 23:01:34 +00:00
|
|
|
switch (mProcessType) {
|
|
|
|
case GeckoProcessType_Content:
|
2017-06-01 14:38:22 +00:00
|
|
|
if (mSandboxLevel > 0) {
|
2016-06-06 13:13:33 +00:00
|
|
|
// For now we treat every failure as fatal in
|
|
|
|
// SetSecurityLevelForContentProcess and just crash there right away.
|
|
|
|
// Should this change in the future then we should also handle the error
|
|
|
|
// here.
|
2019-03-13 09:24:37 +00:00
|
|
|
mSandboxBroker->SetSecurityLevelForContentProcess(mSandboxLevel,
|
|
|
|
mIsFileContent);
|
2014-07-16 23:01:34 +00:00
|
|
|
shouldSandboxCurrentProcess = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GeckoProcessType_Plugin:
|
2015-01-23 08:32:21 +00:00
|
|
|
if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) {
|
2016-06-06 13:13:33 +00:00
|
|
|
bool ok =
|
2019-03-13 09:24:37 +00:00
|
|
|
mSandboxBroker->SetSecurityLevelForPluginProcess(mSandboxLevel);
|
2016-06-06 13:13:33 +00:00
|
|
|
if (!ok) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-01-23 08:32:20 +00:00
|
|
|
shouldSandboxCurrentProcess = true;
|
|
|
|
}
|
2014-07-16 23:01:34 +00:00
|
|
|
break;
|
|
|
|
case GeckoProcessType_IPDLUnitTest:
|
|
|
|
// XXX: We don't sandbox this process type yet
|
|
|
|
break;
|
|
|
|
case GeckoProcessType_GMPlugin:
|
|
|
|
if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
|
2016-04-12 04:12:20 +00:00
|
|
|
// The Widevine CDM on Windows can only load at USER_RESTRICTED,
|
|
|
|
// not at USER_LOCKDOWN. So look in the command line arguments
|
|
|
|
// to see if we're loading the path to the Widevine CDM, and if
|
|
|
|
// so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN.
|
|
|
|
auto level =
|
|
|
|
isWidevine ? SandboxBroker::Restricted : SandboxBroker::LockDown;
|
2019-03-13 09:24:37 +00:00
|
|
|
bool ok = mSandboxBroker->SetSecurityLevelForGMPlugin(level);
|
2016-06-06 13:13:33 +00:00
|
|
|
if (!ok) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-07-16 23:01:34 +00:00
|
|
|
shouldSandboxCurrentProcess = true;
|
|
|
|
}
|
|
|
|
break;
|
2016-06-11 02:27:24 +00:00
|
|
|
case GeckoProcessType_GPU:
|
2017-04-24 16:46:09 +00:00
|
|
|
if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_GPU_SANDBOX")) {
|
|
|
|
// For now we treat every failure as fatal in
|
|
|
|
// SetSecurityLevelForGPUProcess and just crash there right away. Should
|
|
|
|
// this change in the future then we should also handle the error here.
|
2019-03-13 09:24:37 +00:00
|
|
|
mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel);
|
2017-04-24 16:46:09 +00:00
|
|
|
shouldSandboxCurrentProcess = true;
|
|
|
|
}
|
2016-06-11 02:27:24 +00:00
|
|
|
break;
|
2018-06-22 23:30:14 +00:00
|
|
|
case GeckoProcessType_VR:
|
|
|
|
if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_VR_SANDBOX")) {
|
|
|
|
// TODO: Implement sandbox for VR process, Bug 1430043.
|
|
|
|
}
|
|
|
|
break;
|
2018-11-14 18:06:37 +00:00
|
|
|
case GeckoProcessType_RDD:
|
2018-11-29 17:02:16 +00:00
|
|
|
if (!PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) {
|
2019-03-13 09:24:37 +00:00
|
|
|
if (!mSandboxBroker->SetSecurityLevelForRDDProcess()) {
|
2018-11-29 17:02:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
shouldSandboxCurrentProcess = true;
|
2018-11-14 18:06:37 +00:00
|
|
|
}
|
|
|
|
break;
|
2019-01-11 18:57:23 +00:00
|
|
|
case GeckoProcessType_Socket:
|
|
|
|
// TODO - setup sandboxing for the socket process.
|
|
|
|
break;
|
2019-03-13 09:24:52 +00:00
|
|
|
case GeckoProcessType_RemoteSandboxBroker:
|
|
|
|
// We don't sandbox the sandbox launcher...
|
|
|
|
break;
|
2014-07-16 23:01:34 +00:00
|
|
|
case GeckoProcessType_Default:
|
|
|
|
default:
|
|
|
|
MOZ_CRASH("Bad process type in GeckoChildProcessHost");
|
|
|
|
break;
|
|
|
|
};
|
2014-08-30 00:34:26 +00:00
|
|
|
|
|
|
|
if (shouldSandboxCurrentProcess) {
|
|
|
|
for (auto it = mAllowedFilesRead.begin(); it != mAllowedFilesRead.end();
|
|
|
|
++it) {
|
2019-03-13 09:24:37 +00:00
|
|
|
mSandboxBroker->AllowReadFile(it->c_str());
|
2014-08-30 00:34:26 +00:00
|
|
|
}
|
|
|
|
}
|
2018-01-24 15:48:33 +00:00
|
|
|
# endif // defined(MOZ_SANDBOX)
|
2013-11-02 02:09:45 +00:00
|
|
|
|
2012-12-18 16:24:42 +00:00
|
|
|
// Add the application directory path (-appdir path)
|
|
|
|
AddAppDirToCommandLine(cmdLine);
|
|
|
|
|
|
|
|
// XXX Command line params past this point are expected to be at
|
|
|
|
// the end of the command line string, and in a specific order.
|
|
|
|
// See XRE_InitChildProcess in nsEmbedFunction.
|
|
|
|
|
|
|
|
// Win app model id
|
2013-12-03 15:09:50 +00:00
|
|
|
cmdLine.AppendLooseValue(mGroupId.get());
|
2012-12-18 16:24:42 +00:00
|
|
|
|
|
|
|
// Process id
|
2009-10-27 21:52:37 +00:00
|
|
|
cmdLine.AppendLooseValue(UTF8ToWide(pidstring));
|
2010-09-10 17:09:30 +00:00
|
|
|
|
2010-01-12 21:14:38 +00:00
|
|
|
cmdLine.AppendLooseValue(
|
2010-01-13 15:44:10 +00:00
|
|
|
UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
|
2009-10-27 21:52:37 +00:00
|
|
|
|
2018-02-15 15:07:12 +00:00
|
|
|
if (!CrashReporter::IsDummy()) {
|
|
|
|
PROsfd h = PR_FileDesc2NativeHandle(crashAnnotationWritePipe);
|
|
|
|
mLaunchOptions->handles_to_inherit.push_back(reinterpret_cast<HANDLE>(h));
|
|
|
|
std::string hStr = std::to_string(h);
|
|
|
|
cmdLine.AppendLooseValue(UTF8ToWide(hStr));
|
|
|
|
}
|
2017-11-27 20:37:34 +00:00
|
|
|
|
2012-12-18 16:24:42 +00:00
|
|
|
// Process type
|
2010-09-10 17:09:30 +00:00
|
|
|
cmdLine.AppendLooseValue(UTF8ToWide(childProcessType));
|
|
|
|
|
2018-01-24 15:48:33 +00:00
|
|
|
# if defined(MOZ_SANDBOX)
|
2014-07-16 23:01:34 +00:00
|
|
|
if (shouldSandboxCurrentProcess) {
|
Bug 1438678 - Pass early prefs via shared memory instead of the command line. r=bobowen,jld,glandium.
This patch replaces the large -intPrefs/-boolPrefs/-stringPrefs flags with
a short-lived, anonymous, shared memory segment that is used to pass the early
prefs.
Removing the bloat from the command line is nice, but more important is the
fact that this will let us pass more prefs at content process start-up, which
will allow us to remove the early/late prefs split (bug 1436911).
Although this mechanism is only used for prefs, it's conceivable that it could
be used for other data that must be received very early by children, and for
which the command line isn't ideal.
Notable details:
- Much of the patch deals with the various platform-specific ways of passing
handles/fds to children.
- Linux and Mac: we use a fixed fd (8) in combination with the new
GeckoChildProcessHost::AddFdToRemap() function (which ensures the child
won't close the fd).
- Android: like Linux and Mac, but the handles get passed via "parcels" and
we use the new SetPrefsFd() function instead of the fixed fd.
- Windows: there is no need to duplicate the handle because Windows handles
are system-wide. But we do use the new
GeckoChildProcessHost::AddHandleToShare() function to add it to the list of
inheritable handles. We also ensure that list is processed on all paths
(MOZ_SANDBOX with sandbox, MOZ_SANDBOX without sandbox, non-MOZ_SANDBOX) so
that the handles are marked as inheritable. The handle is passed via the
-prefsHandle flag.
The -prefsLen flag is used on all platforms to indicate the size of the
shared memory segment.
- The patch also moves the serialization/deserialization of the prefs in/out of
the shared memory into libpref, which is a better spot for it. (This means
Preferences::MustSendToContentProcesses() can be removed.)
MozReview-Commit-ID: 8fREEBiYFvc
--HG--
extra : rebase_source : 7e4c8ebdbcd7d74d6bd2ab3c9e75a6a17dbd8dfe
2018-02-16 06:54:16 +00:00
|
|
|
// Mark the handles to inherit as inheritable.
|
|
|
|
for (HANDLE h : mLaunchOptions->handles_to_inherit) {
|
2019-03-13 09:24:37 +00:00
|
|
|
mSandboxBroker->AddHandleToShare(h);
|
Bug 1438678 - Pass early prefs via shared memory instead of the command line. r=bobowen,jld,glandium.
This patch replaces the large -intPrefs/-boolPrefs/-stringPrefs flags with
a short-lived, anonymous, shared memory segment that is used to pass the early
prefs.
Removing the bloat from the command line is nice, but more important is the
fact that this will let us pass more prefs at content process start-up, which
will allow us to remove the early/late prefs split (bug 1436911).
Although this mechanism is only used for prefs, it's conceivable that it could
be used for other data that must be received very early by children, and for
which the command line isn't ideal.
Notable details:
- Much of the patch deals with the various platform-specific ways of passing
handles/fds to children.
- Linux and Mac: we use a fixed fd (8) in combination with the new
GeckoChildProcessHost::AddFdToRemap() function (which ensures the child
won't close the fd).
- Android: like Linux and Mac, but the handles get passed via "parcels" and
we use the new SetPrefsFd() function instead of the fixed fd.
- Windows: there is no need to duplicate the handle because Windows handles
are system-wide. But we do use the new
GeckoChildProcessHost::AddHandleToShare() function to add it to the list of
inheritable handles. We also ensure that list is processed on all paths
(MOZ_SANDBOX with sandbox, MOZ_SANDBOX without sandbox, non-MOZ_SANDBOX) so
that the handles are marked as inheritable. The handle is passed via the
-prefsHandle flag.
The -prefsLen flag is used on all platforms to indicate the size of the
shared memory segment.
- The patch also moves the serialization/deserialization of the prefs in/out of
the shared memory into libpref, which is a better spot for it. (This means
Preferences::MustSendToContentProcesses() can be removed.)
MozReview-Commit-ID: 8fREEBiYFvc
--HG--
extra : rebase_source : 7e4c8ebdbcd7d74d6bd2ab3c9e75a6a17dbd8dfe
2018-02-16 06:54:16 +00:00
|
|
|
}
|
|
|
|
|
2019-03-13 09:24:37 +00:00
|
|
|
if (mSandboxBroker->LaunchApp(cmdLine.program().c_str(),
|
|
|
|
cmdLine.command_line_string().c_str(),
|
|
|
|
mLaunchOptions->env_map, mProcessType,
|
|
|
|
mEnableSandboxLogging, &process)) {
|
2016-02-09 08:31:18 +00:00
|
|
|
EnvironmentLog("MOZ_PROCESS_LOG")
|
|
|
|
.print("==> process %d launched child process %d (%S)\n",
|
|
|
|
base::GetCurrentProcId(), base::GetProcId(process),
|
2016-02-25 14:16:10 +00:00
|
|
|
cmdLine.command_line_string().c_str());
|
2019-04-01 21:58:23 +00:00
|
|
|
} else {
|
|
|
|
return false;
|
2016-02-09 08:31:18 +00:00
|
|
|
}
|
2013-11-02 02:09:45 +00:00
|
|
|
} else
|
2018-01-24 15:48:33 +00:00
|
|
|
# endif // defined(MOZ_SANDBOX)
|
2013-11-02 02:09:45 +00:00
|
|
|
{
|
2019-04-01 21:58:23 +00:00
|
|
|
if (!base::LaunchApp(cmdLine, *mLaunchOptions, &process)) {
|
|
|
|
return false;
|
|
|
|
}
|
2015-09-08 10:18:12 +00:00
|
|
|
|
2017-09-13 14:17:39 +00:00
|
|
|
# ifdef MOZ_SANDBOX
|
2016-07-28 06:17:54 +00:00
|
|
|
// We need to be able to duplicate handles to some types of non-sandboxed
|
|
|
|
// child processes.
|
2019-01-14 16:01:48 +00:00
|
|
|
switch (mProcessType) {
|
|
|
|
case GeckoProcessType_Default:
|
|
|
|
MOZ_CRASH("shouldn't be launching a parent process");
|
|
|
|
case GeckoProcessType_Plugin:
|
|
|
|
case GeckoProcessType_IPDLUnitTest:
|
|
|
|
// No handle duplication necessary.
|
|
|
|
break;
|
|
|
|
default:
|
2019-03-13 09:24:52 +00:00
|
|
|
if (!SandboxBroker::AddTargetPeer(process)) {
|
2019-01-14 16:01:48 +00:00
|
|
|
NS_WARNING("Failed to add child process as target peer.");
|
|
|
|
}
|
|
|
|
break;
|
2015-09-08 10:18:12 +00:00
|
|
|
}
|
2017-09-13 14:17:39 +00:00
|
|
|
# endif // MOZ_SANDBOX
|
2013-11-02 02:09:45 +00:00
|
|
|
}
|
2009-11-06 00:24:27 +00:00
|
|
|
|
2017-09-13 14:17:39 +00:00
|
|
|
#else // goes with defined(OS_POSIX)
|
2009-11-06 00:24:27 +00:00
|
|
|
# error Sorry
|
2017-09-13 14:17:39 +00:00
|
|
|
#endif // defined(OS_POSIX)
|
2009-06-29 18:38:29 +00:00
|
|
|
|
2019-04-01 21:58:23 +00:00
|
|
|
MOZ_ASSERT(process);
|
2012-08-07 23:29:32 +00:00
|
|
|
// NB: on OS X, we block much longer than we need to in order to
|
|
|
|
// reach this call, waiting for the child process's task_t. The
|
|
|
|
// best way to fix that is to refactor this file, hard.
|
2011-10-14 07:54:46 +00:00
|
|
|
#if defined(MOZ_WIDGET_COCOA)
|
2010-08-27 13:32:45 +00:00
|
|
|
mChildTask = child_task;
|
2017-09-13 14:17:39 +00:00
|
|
|
#endif // defined(MOZ_WIDGET_COCOA)
|
2009-06-29 18:38:29 +00:00
|
|
|
|
2016-06-23 09:50:37 +00:00
|
|
|
if (!OpenPrivilegedHandle(base::GetProcId(process))
|
|
|
|
#ifdef XP_WIN
|
|
|
|
// If we failed in opening the process handle, try harder by duplicating
|
|
|
|
// one.
|
|
|
|
&& !::DuplicateHandle(::GetCurrentProcess(), process,
|
|
|
|
::GetCurrentProcess(), &mChildProcessHandle,
|
|
|
|
PROCESS_DUP_HANDLE | PROCESS_TERMINATE |
|
|
|
|
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ |
|
|
|
|
SYNCHRONIZE,
|
|
|
|
FALSE, 0)
|
2017-09-13 14:17:39 +00:00
|
|
|
#endif // XP_WIN
|
2016-06-23 09:50:37 +00:00
|
|
|
) {
|
2016-12-02 21:46:53 +00:00
|
|
|
MOZ_CRASH("cannot open handle to child process");
|
2012-08-07 23:29:32 +00:00
|
|
|
}
|
2018-12-19 15:29:09 +00:00
|
|
|
|
2017-11-27 20:37:34 +00:00
|
|
|
CrashReporter::RegisterChildCrashAnnotationFileDescriptor(
|
2018-12-19 15:29:09 +00:00
|
|
|
base::GetProcId(process), crashAnnotationReadPipe.forget());
|
2017-11-27 20:37:34 +00:00
|
|
|
|
2019-02-05 00:15:20 +00:00
|
|
|
{
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
2019-02-05 00:15:22 +00:00
|
|
|
// This runs on a launch thread, but the OnChannel{Connected,Error}
|
|
|
|
// callbacks run on the I/O thread, so it's possible that the state already
|
|
|
|
// advanced beyond PROCESS_CREATED.
|
|
|
|
if (mProcessState < PROCESS_CREATED) {
|
|
|
|
mProcessState = PROCESS_CREATED;
|
|
|
|
}
|
2019-02-05 00:15:20 +00:00
|
|
|
lock.Notify();
|
|
|
|
}
|
2012-08-07 23:29:32 +00:00
|
|
|
|
2017-09-09 02:35:06 +00:00
|
|
|
mLaunchOptions = nullptr;
|
2018-11-28 20:42:33 +00:00
|
|
|
|
|
|
|
Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS, startTS);
|
|
|
|
|
2019-02-05 00:15:20 +00:00
|
|
|
// Warning: resolving the promise allows `this` to be deleted.
|
|
|
|
mHandlePromise->Resolve(process, __func__);
|
2009-06-29 18:38:29 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-07 23:29:32 +00:00
|
|
|
bool GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid) {
|
|
|
|
if (mChildProcessHandle) {
|
|
|
|
MOZ_ASSERT(aPid == base::GetProcId(mChildProcessHandle));
|
2016-06-23 09:50:37 +00:00
|
|
|
return true;
|
2012-08-07 23:29:32 +00:00
|
|
|
}
|
2016-06-23 09:50:37 +00:00
|
|
|
|
|
|
|
return base::OpenPrivilegedProcessHandle(aPid, &mChildProcessHandle);
|
2012-08-07 23:29:32 +00:00
|
|
|
}
|
2009-10-27 21:52:37 +00:00
|
|
|
|
2012-09-17 08:37:20 +00:00
|
|
|
void GeckoChildProcessHost::OnChannelConnected(int32_t peer_pid) {
|
2016-06-23 09:50:37 +00:00
|
|
|
if (!OpenPrivilegedHandle(peer_pid)) {
|
2016-12-02 21:46:53 +00:00
|
|
|
MOZ_CRASH("can't open handle to child process");
|
2012-08-07 23:29:32 +00:00
|
|
|
}
|
2016-06-23 09:50:37 +00:00
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
mProcessState = PROCESS_CONNECTED;
|
|
|
|
lock.Notify();
|
2009-07-14 05:12:50 +00:00
|
|
|
}
|
2009-07-20 18:14:41 +00:00
|
|
|
|
2016-02-29 23:43:35 +00:00
|
|
|
void GeckoChildProcessHost::OnMessageReceived(IPC::Message&& aMsg) {
|
2012-07-14 21:21:32 +00:00
|
|
|
// We never process messages ourself, just save them up for the next
|
|
|
|
// listener.
|
2018-05-30 19:15:35 +00:00
|
|
|
mQueue.push(std::move(aMsg));
|
2009-06-29 18:38:29 +00:00
|
|
|
}
|
2012-07-14 21:21:32 +00:00
|
|
|
|
2009-06-29 18:38:29 +00:00
|
|
|
void GeckoChildProcessHost::OnChannelError() {
|
2014-01-12 03:51:00 +00:00
|
|
|
// Update the process state to an error state if we have a channel
|
|
|
|
// error before we're connected. This fixes certain failures,
|
|
|
|
// but does not address the full range of possible issues described
|
|
|
|
// in the FIXME comment below.
|
|
|
|
MonitorAutoLock lock(mMonitor);
|
|
|
|
if (mProcessState < PROCESS_CONNECTED) {
|
|
|
|
mProcessState = PROCESS_ERROR;
|
|
|
|
lock.Notify();
|
|
|
|
}
|
2012-07-14 21:21:32 +00:00
|
|
|
// FIXME/bug 773925: save up this error for the next listener.
|
|
|
|
}
|
|
|
|
|
2018-11-28 20:42:31 +00:00
|
|
|
RefPtr<GeckoChildProcessHost::HandlePromise>
|
|
|
|
GeckoChildProcessHost::WhenProcessHandleReady() {
|
|
|
|
MOZ_ASSERT(mHandlePromise != nullptr);
|
|
|
|
return mHandlePromise;
|
|
|
|
}
|
|
|
|
|
2012-07-14 21:21:32 +00:00
|
|
|
void GeckoChildProcessHost::GetQueuedMessages(std::queue<IPC::Message>& queue) {
|
|
|
|
// If this is called off the IO thread, bad things will happen.
|
|
|
|
DCHECK(MessageLoopForIO::current());
|
|
|
|
swap(queue, mQueue);
|
|
|
|
// We expect the next listener to take over processing of our queue.
|
2009-06-29 18:38:29 +00:00
|
|
|
}
|
2009-09-03 00:18:27 +00:00
|
|
|
|
2016-10-05 23:37:35 +00:00
|
|
|
#ifdef MOZ_WIDGET_ANDROID
|
|
|
|
void GeckoChildProcessHost::LaunchAndroidService(
|
|
|
|
const char* type, const std::vector<std::string>& argv,
|
|
|
|
const base::file_handle_mapping_vector& fds_to_remap,
|
|
|
|
ProcessHandle* process_handle) {
|
2018-07-13 18:06:58 +00:00
|
|
|
MOZ_RELEASE_ASSERT((2 <= fds_to_remap.size()) && (fds_to_remap.size() <= 5));
|
2017-10-05 02:28:43 +00:00
|
|
|
JNIEnv* const env = mozilla::jni::GetEnvForThread();
|
2016-10-05 23:37:35 +00:00
|
|
|
MOZ_ASSERT(env);
|
|
|
|
|
2017-10-05 02:28:43 +00:00
|
|
|
const int argvSize = argv.size();
|
|
|
|
jni::ObjectArray::LocalRef jargs =
|
|
|
|
jni::ObjectArray::New<jni::String>(argvSize);
|
2016-10-05 23:37:35 +00:00
|
|
|
for (int ix = 0; ix < argvSize; ix++) {
|
|
|
|
jargs->SetElement(ix, jni::StringParam(argv[ix].c_str(), env));
|
|
|
|
}
|
Bug 1438678 - Pass early prefs via shared memory instead of the command line. r=bobowen,jld,glandium.
This patch replaces the large -intPrefs/-boolPrefs/-stringPrefs flags with
a short-lived, anonymous, shared memory segment that is used to pass the early
prefs.
Removing the bloat from the command line is nice, but more important is the
fact that this will let us pass more prefs at content process start-up, which
will allow us to remove the early/late prefs split (bug 1436911).
Although this mechanism is only used for prefs, it's conceivable that it could
be used for other data that must be received very early by children, and for
which the command line isn't ideal.
Notable details:
- Much of the patch deals with the various platform-specific ways of passing
handles/fds to children.
- Linux and Mac: we use a fixed fd (8) in combination with the new
GeckoChildProcessHost::AddFdToRemap() function (which ensures the child
won't close the fd).
- Android: like Linux and Mac, but the handles get passed via "parcels" and
we use the new SetPrefsFd() function instead of the fixed fd.
- Windows: there is no need to duplicate the handle because Windows handles
are system-wide. But we do use the new
GeckoChildProcessHost::AddHandleToShare() function to add it to the list of
inheritable handles. We also ensure that list is processed on all paths
(MOZ_SANDBOX with sandbox, MOZ_SANDBOX without sandbox, non-MOZ_SANDBOX) so
that the handles are marked as inheritable. The handle is passed via the
-prefsHandle flag.
The -prefsLen flag is used on all platforms to indicate the size of the
shared memory segment.
- The patch also moves the serialization/deserialization of the prefs in/out of
the shared memory into libpref, which is a better spot for it. (This means
Preferences::MustSendToContentProcesses() can be removed.)
MozReview-Commit-ID: 8fREEBiYFvc
--HG--
extra : rebase_source : 7e4c8ebdbcd7d74d6bd2ab3c9e75a6a17dbd8dfe
2018-02-16 06:54:16 +00:00
|
|
|
|
|
|
|
// XXX: this processing depends entirely on the internals of
|
|
|
|
// ContentParent::LaunchSubprocess()
|
2018-09-14 17:28:38 +00:00
|
|
|
// GeckoChildProcessHost::PerformAsyncLaunch(), and the order in
|
Bug 1438678 - Pass early prefs via shared memory instead of the command line. r=bobowen,jld,glandium.
This patch replaces the large -intPrefs/-boolPrefs/-stringPrefs flags with
a short-lived, anonymous, shared memory segment that is used to pass the early
prefs.
Removing the bloat from the command line is nice, but more important is the
fact that this will let us pass more prefs at content process start-up, which
will allow us to remove the early/late prefs split (bug 1436911).
Although this mechanism is only used for prefs, it's conceivable that it could
be used for other data that must be received very early by children, and for
which the command line isn't ideal.
Notable details:
- Much of the patch deals with the various platform-specific ways of passing
handles/fds to children.
- Linux and Mac: we use a fixed fd (8) in combination with the new
GeckoChildProcessHost::AddFdToRemap() function (which ensures the child
won't close the fd).
- Android: like Linux and Mac, but the handles get passed via "parcels" and
we use the new SetPrefsFd() function instead of the fixed fd.
- Windows: there is no need to duplicate the handle because Windows handles
are system-wide. But we do use the new
GeckoChildProcessHost::AddHandleToShare() function to add it to the list of
inheritable handles. We also ensure that list is processed on all paths
(MOZ_SANDBOX with sandbox, MOZ_SANDBOX without sandbox, non-MOZ_SANDBOX) so
that the handles are marked as inheritable. The handle is passed via the
-prefsHandle flag.
The -prefsLen flag is used on all platforms to indicate the size of the
shared memory segment.
- The patch also moves the serialization/deserialization of the prefs in/out of
the shared memory into libpref, which is a better spot for it. (This means
Preferences::MustSendToContentProcesses() can be removed.)
MozReview-Commit-ID: 8fREEBiYFvc
--HG--
extra : rebase_source : 7e4c8ebdbcd7d74d6bd2ab3c9e75a6a17dbd8dfe
2018-02-16 06:54:16 +00:00
|
|
|
// which they append to fds_to_remap. There must be a better way to do it.
|
|
|
|
// See bug 1440207.
|
|
|
|
int32_t prefsFd = fds_to_remap[0].first;
|
2018-07-13 18:06:58 +00:00
|
|
|
int32_t prefMapFd = fds_to_remap[1].first;
|
|
|
|
int32_t ipcFd = fds_to_remap[2].first;
|
2018-02-21 19:37:22 +00:00
|
|
|
int32_t crashFd = -1;
|
|
|
|
int32_t crashAnnotationFd = -1;
|
Bug 1438678 - Pass early prefs via shared memory instead of the command line. r=bobowen,jld,glandium.
This patch replaces the large -intPrefs/-boolPrefs/-stringPrefs flags with
a short-lived, anonymous, shared memory segment that is used to pass the early
prefs.
Removing the bloat from the command line is nice, but more important is the
fact that this will let us pass more prefs at content process start-up, which
will allow us to remove the early/late prefs split (bug 1436911).
Although this mechanism is only used for prefs, it's conceivable that it could
be used for other data that must be received very early by children, and for
which the command line isn't ideal.
Notable details:
- Much of the patch deals with the various platform-specific ways of passing
handles/fds to children.
- Linux and Mac: we use a fixed fd (8) in combination with the new
GeckoChildProcessHost::AddFdToRemap() function (which ensures the child
won't close the fd).
- Android: like Linux and Mac, but the handles get passed via "parcels" and
we use the new SetPrefsFd() function instead of the fixed fd.
- Windows: there is no need to duplicate the handle because Windows handles
are system-wide. But we do use the new
GeckoChildProcessHost::AddHandleToShare() function to add it to the list of
inheritable handles. We also ensure that list is processed on all paths
(MOZ_SANDBOX with sandbox, MOZ_SANDBOX without sandbox, non-MOZ_SANDBOX) so
that the handles are marked as inheritable. The handle is passed via the
-prefsHandle flag.
The -prefsLen flag is used on all platforms to indicate the size of the
shared memory segment.
- The patch also moves the serialization/deserialization of the prefs in/out of
the shared memory into libpref, which is a better spot for it. (This means
Preferences::MustSendToContentProcesses() can be removed.)
MozReview-Commit-ID: 8fREEBiYFvc
--HG--
extra : rebase_source : 7e4c8ebdbcd7d74d6bd2ab3c9e75a6a17dbd8dfe
2018-02-16 06:54:16 +00:00
|
|
|
if (fds_to_remap.size() == 4) {
|
|
|
|
crashAnnotationFd = fds_to_remap[3].first;
|
2018-02-21 19:37:22 +00:00
|
|
|
}
|
2018-07-13 18:06:58 +00:00
|
|
|
if (fds_to_remap.size() == 5) {
|
|
|
|
crashFd = fds_to_remap[3].first;
|
|
|
|
crashAnnotationFd = fds_to_remap[4].first;
|
|
|
|
}
|
Bug 1438678 - Pass early prefs via shared memory instead of the command line. r=bobowen,jld,glandium.
This patch replaces the large -intPrefs/-boolPrefs/-stringPrefs flags with
a short-lived, anonymous, shared memory segment that is used to pass the early
prefs.
Removing the bloat from the command line is nice, but more important is the
fact that this will let us pass more prefs at content process start-up, which
will allow us to remove the early/late prefs split (bug 1436911).
Although this mechanism is only used for prefs, it's conceivable that it could
be used for other data that must be received very early by children, and for
which the command line isn't ideal.
Notable details:
- Much of the patch deals with the various platform-specific ways of passing
handles/fds to children.
- Linux and Mac: we use a fixed fd (8) in combination with the new
GeckoChildProcessHost::AddFdToRemap() function (which ensures the child
won't close the fd).
- Android: like Linux and Mac, but the handles get passed via "parcels" and
we use the new SetPrefsFd() function instead of the fixed fd.
- Windows: there is no need to duplicate the handle because Windows handles
are system-wide. But we do use the new
GeckoChildProcessHost::AddHandleToShare() function to add it to the list of
inheritable handles. We also ensure that list is processed on all paths
(MOZ_SANDBOX with sandbox, MOZ_SANDBOX without sandbox, non-MOZ_SANDBOX) so
that the handles are marked as inheritable. The handle is passed via the
-prefsHandle flag.
The -prefsLen flag is used on all platforms to indicate the size of the
shared memory segment.
- The patch also moves the serialization/deserialization of the prefs in/out of
the shared memory into libpref, which is a better spot for it. (This means
Preferences::MustSendToContentProcesses() can be removed.)
MozReview-Commit-ID: 8fREEBiYFvc
--HG--
extra : rebase_source : 7e4c8ebdbcd7d74d6bd2ab3c9e75a6a17dbd8dfe
2018-02-16 06:54:16 +00:00
|
|
|
|
2018-07-13 18:06:58 +00:00
|
|
|
int32_t handle = java::GeckoProcessManager::Start(
|
|
|
|
type, jargs, prefsFd, prefMapFd, ipcFd, crashFd, crashAnnotationFd);
|
2016-10-05 23:37:35 +00:00
|
|
|
|
|
|
|
if (process_handle) {
|
|
|
|
*process_handle = handle;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2019-03-28 02:25:52 +00:00
|
|
|
|
|
|
|
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
|
|
|
void GeckoChildProcessHost::AppendMacSandboxParams(StringVector& aArgs) {
|
|
|
|
MacSandboxInfo info;
|
|
|
|
FillMacSandboxInfo(info);
|
|
|
|
info.AppendAsParams(aArgs);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill |aInfo| with the flags needed to launch the utility sandbox
|
|
|
|
/* static */
|
|
|
|
void GeckoChildProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
|
|
|
aInfo.type = GetDefaultMacSandboxType();
|
|
|
|
aInfo.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
|
|
|
|
PR_GetEnv("MOZ_SANDBOX_LOGGING");
|
|
|
|
|
|
|
|
nsAutoCString appPath;
|
|
|
|
if (!nsMacUtilsImpl::GetAppPath(appPath)) {
|
|
|
|
MOZ_CRASH("Failed to get app path");
|
|
|
|
}
|
|
|
|
aInfo.appPath.assign(appPath.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
void GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
|
|
|
GeckoChildProcessHost::StaticFillMacSandboxInfo(aInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// If early sandbox startup is enabled for this process type, map the
|
|
|
|
// process type to the sandbox type and enable the sandbox. Returns true
|
|
|
|
// if no errors were encountered or if early sandbox startup is not
|
|
|
|
// enabled for this process. Returns false if an error was encountered.
|
|
|
|
//
|
|
|
|
/* static */
|
|
|
|
bool GeckoChildProcessHost::StartMacSandbox(int aArgc, char** aArgv,
|
|
|
|
std::string& aErrorMessage) {
|
|
|
|
MacSandboxType sandboxType = MacSandboxType_Invalid;
|
|
|
|
switch (XRE_GetProcessType()) {
|
|
|
|
// For now, only support early sandbox startup for content
|
|
|
|
// processes. Add case statements for the additional process
|
|
|
|
// types once early sandbox startup is implemented for them.
|
|
|
|
case GeckoProcessType_Content:
|
|
|
|
// Content processes don't use GeckoChildProcessHost
|
|
|
|
// to configure sandboxing so hard code the sandbox type.
|
|
|
|
sandboxType = MacSandboxType_Content;
|
|
|
|
break;
|
2019-03-28 02:25:50 +00:00
|
|
|
case GeckoProcessType_RDD:
|
|
|
|
sandboxType = RDDProcessHost::GetMacSandboxType();
|
|
|
|
break;
|
2019-03-28 02:25:52 +00:00
|
|
|
default:
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return mozilla::StartMacSandboxIfEnabled(sandboxType, aArgc, aArgv,
|
|
|
|
aErrorMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* XP_MACOSX && MOZ_SANDBOX */
|