Bug 1858509 add thread-safety annotations around MediaSourceDemuxer::mMonitor r=alwu
[gecko.git] / ipc / glue / GeckoChildProcessHost.cpp
blob7d58593d6288f951d0155d2564c92c30d24ec406
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "GeckoChildProcessHost.h"
9 #include "base/command_line.h"
10 #include "base/process.h"
11 #include "base/process_util.h"
12 #include "base/string_util.h"
13 #include "base/task.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/process_watcher.h"
16 #ifdef MOZ_WIDGET_COCOA
17 # include <bsm/libbsm.h>
18 # include <mach/mach_traps.h>
19 # include <servers/bootstrap.h>
20 # include "SharedMemoryBasic.h"
21 # include "base/rand_util.h"
22 # include "chrome/common/mach_ipc_mac.h"
23 # include "mozilla/StaticPrefs_media.h"
24 # include "nsILocalFileMac.h"
25 #endif
27 #include "GeckoProfiler.h"
28 #include "MainThreadUtils.h"
29 #include "mozilla/Preferences.h"
30 #include "mozilla/Sprintf.h"
31 #include "nsXPCOMPrivate.h"
32 #include "prenv.h"
33 #include "prerror.h"
35 #if defined(MOZ_SANDBOX)
36 # include "mozilla/SandboxSettings.h"
37 # include "nsAppDirectoryServiceDefs.h"
38 #endif
40 #include <sys/stat.h>
42 #include "ProtocolUtils.h"
43 #include "mozilla/LinkedList.h"
44 #include "mozilla/Logging.h"
45 #include "mozilla/Maybe.h"
46 #include "mozilla/GeckoArgs.h"
47 #include "mozilla/Omnijar.h"
48 #include "mozilla/RDDProcessHost.h"
49 #include "mozilla/Services.h"
50 #include "mozilla/SharedThreadPool.h"
51 #include "mozilla/StaticMutex.h"
52 #include "mozilla/TaskQueue.h"
53 #include "mozilla/Telemetry.h"
54 #include "mozilla/UniquePtrExtensions.h"
55 #include "mozilla/ipc/BrowserProcessSubThread.h"
56 #include "mozilla/ipc/EnvironmentMap.h"
57 #include "mozilla/ipc/NodeController.h"
58 #include "mozilla/net/SocketProcessHost.h"
59 #include "nsDirectoryService.h"
60 #include "nsDirectoryServiceDefs.h"
61 #include "nsExceptionHandler.h"
62 #include "nsIFile.h"
63 #include "nsIObserverService.h"
64 #include "nsPrintfCString.h"
66 #ifdef XP_WIN
67 # include <stdlib.h>
69 # include "nsIWinTaskbar.h"
70 # define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
72 # if defined(MOZ_SANDBOX)
73 # include "WinUtils.h"
74 # include "mozilla/Preferences.h"
75 # include "mozilla/sandboxing/sandboxLogging.h"
76 # if defined(_ARM64_)
77 # include "mozilla/remoteSandboxBroker.h"
78 # endif
79 # endif
81 # include "mozilla/NativeNt.h"
82 # include "mozilla/CacheNtDllThunk.h"
83 #endif
85 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
86 # include "mozilla/SandboxLaunch.h"
87 #endif
89 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
90 # include "GMPProcessParent.h"
91 # include "nsMacUtilsImpl.h"
92 #endif
94 #include "mozilla/ipc/UtilityProcessHost.h"
95 #include "mozilla/ipc/UtilityProcessSandboxing.h"
97 #include "nsClassHashtable.h"
98 #include "nsHashKeys.h"
99 #include "nsNativeCharsetUtils.h"
100 #include "nsTArray.h"
101 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
102 #include "nsIThread.h"
104 using mozilla::MonitorAutoLock;
105 using mozilla::Preferences;
106 using mozilla::StaticMutexAutoLock;
108 #ifdef MOZ_WIDGET_ANDROID
109 # include "AndroidBridge.h"
110 # include "mozilla/java/GeckoProcessManagerWrappers.h"
111 # include "mozilla/java/GeckoProcessTypeWrappers.h"
112 # include "mozilla/java/GeckoResultWrappers.h"
113 # include "mozilla/jni/Refs.h"
114 # include "mozilla/jni/Utils.h"
115 #endif
117 #ifdef MOZ_ENABLE_FORKSERVER
118 # include "mozilla/ipc/ForkServiceChild.h"
119 #endif
121 static bool ShouldHaveDirectoryService() {
122 return GeckoProcessType_Default == XRE_GetProcessType();
125 namespace mozilla {
126 namespace ipc {
128 struct LaunchResults {
129 base::ProcessHandle mHandle = 0;
130 #ifdef XP_MACOSX
131 task_t mChildTask = MACH_PORT_NULL;
132 #endif
133 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
134 RefPtr<AbstractSandboxBroker> mSandboxBroker;
135 #endif
137 typedef mozilla::MozPromise<LaunchResults, LaunchError, true>
138 ProcessLaunchPromise;
140 static Atomic<int32_t> gChildCounter;
142 static inline nsISerialEventTarget* IOThread() {
143 return XRE_GetIOMessageLoop()->SerialEventTarget();
146 class BaseProcessLauncher {
147 public:
148 BaseProcessLauncher(GeckoChildProcessHost* aHost,
149 std::vector<std::string>&& aExtraOpts)
150 : mProcessType(aHost->mProcessType),
151 mLaunchOptions(std::move(aHost->mLaunchOptions)),
152 mExtraOpts(std::move(aExtraOpts)),
153 #ifdef XP_WIN
154 mGroupId(aHost->mGroupId),
155 #endif
156 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
157 mAllowedFilesRead(aHost->mAllowedFilesRead),
158 mSandboxLevel(aHost->mSandboxLevel),
159 mSandbox(aHost->mSandbox),
160 mIsFileContent(aHost->mIsFileContent),
161 mEnableSandboxLogging(aHost->mEnableSandboxLogging),
162 #endif
163 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
164 mDisableOSActivityMode(aHost->mDisableOSActivityMode),
165 #endif
166 mTmpDirName(aHost->mTmpDirName),
167 mChildId(++gChildCounter) {
168 SprintfLiteral(mPidString, "%" PRIPID, base::GetCurrentProcId());
169 aHost->mInitialChannelId.ToProvidedString(mInitialChannelIdString);
171 // Compute the serial event target we'll use for launching.
172 nsCOMPtr<nsIEventTarget> threadOrPool = GetIPCLauncher();
173 mLaunchThread =
174 TaskQueue::Create(threadOrPool.forget(), "BaseProcessLauncher");
176 if (ShouldHaveDirectoryService()) {
177 // "Current process directory" means the app dir, not the current
178 // working dir or similar.
179 mozilla::Unused
180 << nsDirectoryService::gService->GetCurrentProcessDirectory(
181 getter_AddRefs(mAppDir));
185 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BaseProcessLauncher);
187 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
188 void SetLaunchArchitecture(uint32_t aLaunchArch) {
189 mLaunchArch = aLaunchArch;
191 #endif
193 RefPtr<ProcessLaunchPromise> Launch(GeckoChildProcessHost*);
195 protected:
196 virtual ~BaseProcessLauncher() = default;
198 RefPtr<ProcessLaunchPromise> PerformAsyncLaunch();
199 RefPtr<ProcessLaunchPromise> FinishLaunch();
201 // Overrideable hooks. If superclass behavior is invoked, it's always at the
202 // top of the override.
203 virtual Result<Ok, LaunchError> DoSetup();
204 virtual RefPtr<ProcessHandlePromise> DoLaunch() = 0;
205 virtual Result<Ok, LaunchError> DoFinishLaunch();
207 void MapChildLogging();
209 static BinPathType GetPathToBinary(FilePath&, GeckoProcessType);
211 void GetChildLogName(const char* origLogName, nsACString& buffer);
213 const char* ChildProcessType() {
214 return XRE_GeckoProcessTypeToString(mProcessType);
217 nsCOMPtr<nsISerialEventTarget> mLaunchThread;
218 GeckoProcessType mProcessType;
219 UniquePtr<base::LaunchOptions> mLaunchOptions;
220 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
221 uint32_t mLaunchArch = base::PROCESS_ARCH_INVALID;
222 #endif
223 std::vector<std::string> mExtraOpts;
224 #ifdef XP_WIN
225 nsString mGroupId;
226 #endif
227 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
228 std::vector<std::wstring> mAllowedFilesRead;
229 int32_t mSandboxLevel;
230 SandboxingKind mSandbox;
231 bool mIsFileContent;
232 bool mEnableSandboxLogging;
233 #endif
234 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
235 // Controls whether or not the process will be launched with
236 // environment variable OS_ACTIVITY_MODE set to "disabled".
237 bool mDisableOSActivityMode;
238 #endif
239 nsCString mTmpDirName;
240 LaunchResults mResults = LaunchResults();
241 int32_t mChildId;
242 TimeStamp mStartTimeStamp = TimeStamp::Now();
243 char mPidString[32];
244 char mInitialChannelIdString[NSID_LENGTH];
246 // Set during launch.
247 IPC::Channel::ChannelHandle mClientChannelHandle;
248 nsCOMPtr<nsIFile> mAppDir;
251 #ifdef XP_WIN
252 class WindowsProcessLauncher : public BaseProcessLauncher {
253 public:
254 WindowsProcessLauncher(GeckoChildProcessHost* aHost,
255 std::vector<std::string>&& aExtraOpts)
256 : BaseProcessLauncher(aHost, std::move(aExtraOpts)),
257 mCachedNtdllThunk(GetCachedNtDllThunk()),
258 mWerDataPointer(&(aHost->mWerData)) {}
260 protected:
261 virtual Result<Ok, LaunchError> DoSetup() override;
262 virtual RefPtr<ProcessHandlePromise> DoLaunch() override;
263 virtual Result<Ok, LaunchError> DoFinishLaunch() override;
265 mozilla::Maybe<CommandLine> mCmdLine;
266 bool mUseSandbox = false;
268 const Buffer<IMAGE_THUNK_DATA>* mCachedNtdllThunk;
269 CrashReporter::WindowsErrorReportingData const* mWerDataPointer;
271 typedef WindowsProcessLauncher ProcessLauncher;
272 #endif // XP_WIN
274 #ifdef XP_UNIX
275 class PosixProcessLauncher : public BaseProcessLauncher {
276 public:
277 PosixProcessLauncher(GeckoChildProcessHost* aHost,
278 std::vector<std::string>&& aExtraOpts)
279 : BaseProcessLauncher(aHost, std::move(aExtraOpts)),
280 mProfileDir(aHost->mProfileDir),
281 mChannelDstFd(IPC::Channel::GetClientChannelHandle()) {}
283 protected:
284 virtual Result<Ok, LaunchError> DoSetup() override;
285 virtual RefPtr<ProcessHandlePromise> DoLaunch() override;
287 nsCOMPtr<nsIFile> mProfileDir;
289 std::vector<std::string> mChildArgv;
290 int mChannelDstFd;
293 # if defined(XP_MACOSX)
294 class MacProcessLauncher : public PosixProcessLauncher {
295 public:
296 MacProcessLauncher(GeckoChildProcessHost* aHost,
297 std::vector<std::string>&& aExtraOpts)
298 : PosixProcessLauncher(aHost, std::move(aExtraOpts)),
299 // Put a random number into the channel name, so that
300 // a compromised renderer can't pretend being the child
301 // that's forked off.
302 mMachConnectionName(
303 StringPrintf("org.mozilla.machname.%d",
304 base::RandInt(0, std::numeric_limits<int>::max()))) {
305 MOZ_ASSERT(mMachConnectionName.size() < BOOTSTRAP_MAX_NAME_LEN);
308 protected:
309 virtual Result<Ok, LaunchError> DoFinishLaunch() override;
311 std::string mMachConnectionName;
312 // We add a mach port to the command line so the child can communicate its
313 // 'task_t' back to the parent.
314 mozilla::UniqueMachReceiveRight mParentRecvPort;
316 friend class PosixProcessLauncher;
318 typedef MacProcessLauncher ProcessLauncher;
319 # elif defined(MOZ_WIDGET_ANDROID)
320 class AndroidProcessLauncher : public PosixProcessLauncher {
321 public:
322 AndroidProcessLauncher(GeckoChildProcessHost* aHost,
323 std::vector<std::string>&& aExtraOpts)
324 : PosixProcessLauncher(aHost, std::move(aExtraOpts)) {}
326 protected:
327 virtual RefPtr<ProcessHandlePromise> DoLaunch() override;
328 RefPtr<ProcessHandlePromise> LaunchAndroidService(
329 const GeckoProcessType aType, const std::vector<std::string>& argv,
330 const base::file_handle_mapping_vector& fds_to_remap);
332 typedef AndroidProcessLauncher ProcessLauncher;
333 // NB: Technically Android is linux (i.e. XP_LINUX is defined), but we want
334 // orthogonal IPC machinery there. Conversely, there are tier-3 non-Linux
335 // platforms (BSD and Solaris) where we want the "linux" IPC machinery. So
336 // we use MOZ_WIDGET_* to choose the platform backend.
337 # elif defined(MOZ_WIDGET_GTK)
338 class LinuxProcessLauncher : public PosixProcessLauncher {
339 public:
340 LinuxProcessLauncher(GeckoChildProcessHost* aHost,
341 std::vector<std::string>&& aExtraOpts)
342 : PosixProcessLauncher(aHost, std::move(aExtraOpts)) {}
344 protected:
345 virtual Result<Ok, LaunchError> DoSetup() override;
347 typedef LinuxProcessLauncher ProcessLauncher;
348 # elif
349 # error "Unknown platform"
350 # endif
351 #endif // XP_UNIX
353 using base::ProcessHandle;
354 using mozilla::ipc::BaseProcessLauncher;
355 using mozilla::ipc::ProcessLauncher;
357 mozilla::StaticAutoPtr<mozilla::LinkedList<GeckoChildProcessHost>>
358 GeckoChildProcessHost::sGeckoChildProcessHosts;
360 mozilla::StaticMutex GeckoChildProcessHost::sMutex;
362 GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
363 bool aIsFileContent)
364 : mProcessType(aProcessType),
365 mIsFileContent(aIsFileContent),
366 mMonitor("mozilla.ipc.GeckoChildProcessHost.mMonitor"),
367 mLaunchOptions(MakeUnique<base::LaunchOptions>()),
368 mInitialChannelId(nsID::GenerateUUID()),
369 mProcessState(CREATING_CHANNEL),
370 #ifdef XP_WIN
371 mGroupId(u"-"),
372 mWerData{.mWerNotifyProc = CrashReporter::WerNotifyProc,
373 .mChildPid = 0,
374 .mMinidumpFile = {}},
375 #endif
376 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
377 mEnableSandboxLogging(false),
378 mSandboxLevel(0),
379 #endif
380 mHandleLock("mozilla.ipc.GeckoChildProcessHost.mHandleLock"),
381 mChildProcessHandle(0),
382 #if defined(MOZ_WIDGET_COCOA)
383 mChildTask(MACH_PORT_NULL),
384 #endif
385 #if defined(MOZ_SANDBOX) && defined(XP_MACOSX)
386 mDisableOSActivityMode(false),
387 #endif
388 mDestroying(false) {
389 MOZ_COUNT_CTOR(GeckoChildProcessHost);
390 StaticMutexAutoLock lock(sMutex);
391 if (!sGeckoChildProcessHosts) {
392 sGeckoChildProcessHosts = new mozilla::LinkedList<GeckoChildProcessHost>();
394 sGeckoChildProcessHosts->insertBack(this);
395 #if defined(MOZ_SANDBOX) && defined(XP_LINUX)
396 if (aProcessType == GeckoProcessType_Content) {
397 # if defined(MOZ_CONTENT_TEMP_DIR)
398 // The content process needs the content temp dir:
399 nsCOMPtr<nsIFile> contentTempDir;
400 nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
401 getter_AddRefs(contentTempDir));
402 if (NS_SUCCEEDED(rv)) {
403 contentTempDir->GetNativePath(mTmpDirName);
405 # endif
406 } else if (aProcessType == GeckoProcessType_RDD) {
407 // The RDD process makes limited use of EGL. If Mesa's shader
408 // cache is enabled and the directory isn't explicitly set, then
409 // it will try to getpwuid() the user which can cause problems
410 // with sandboxing. Because we shouldn't need shader caching in
411 // this process, we just disable the cache to prevent that.
412 mLaunchOptions->env_map["MESA_GLSL_CACHE_DISABLE"] = "true";
413 mLaunchOptions->env_map["MESA_SHADER_CACHE_DISABLE"] = "true";
414 // In case the nvidia driver is also loaded:
415 mLaunchOptions->env_map["__GL_SHADER_DISK_CACHE"] = "0";
417 #endif
418 #if defined(MOZ_ENABLE_FORKSERVER)
419 if (aProcessType != GeckoProcessType_ForkServer && ForkServiceChild::Get()) {
420 mLaunchOptions->use_forkserver = true;
422 #endif
425 GeckoChildProcessHost::~GeckoChildProcessHost()
428 AssertIOThread();
429 MOZ_RELEASE_ASSERT(mDestroying);
431 MOZ_COUNT_DTOR(GeckoChildProcessHost);
434 mozilla::AutoWriteLock hLock(mHandleLock);
435 #if defined(MOZ_WIDGET_COCOA)
436 if (mChildTask != MACH_PORT_NULL) {
437 mach_port_deallocate(mach_task_self(), mChildTask);
439 #endif
441 if (mChildProcessHandle != 0) {
442 ProcessWatcher::EnsureProcessTerminated(
443 mChildProcessHandle
444 #ifdef NS_FREE_PERMANENT_DATA
445 // If we're doing leak logging, shutdown can be slow.
447 false // don't "force"
448 #endif
450 mChildProcessHandle = 0;
454 #if defined(MOZ_SANDBOX) && defined(XP_WIN)
455 if (mSandboxBroker) {
456 mSandboxBroker->Shutdown();
457 mSandboxBroker = nullptr;
459 #endif
462 base::ProcessHandle GeckoChildProcessHost::GetChildProcessHandle() {
463 mozilla::AutoReadLock handleLock(mHandleLock);
464 return mChildProcessHandle;
467 base::ProcessId GeckoChildProcessHost::GetChildProcessId() {
468 mozilla::AutoReadLock handleLock(mHandleLock);
469 if (!mChildProcessHandle) {
470 return 0;
472 return base::GetProcId(mChildProcessHandle);
475 #ifdef XP_MACOSX
476 task_t GeckoChildProcessHost::GetChildTask() {
477 mozilla::AutoReadLock handleLock(mHandleLock);
478 return mChildTask;
480 #endif
482 void GeckoChildProcessHost::RemoveFromProcessList() {
483 StaticMutexAutoLock lock(sMutex);
484 if (!sGeckoChildProcessHosts) {
485 return;
487 LinkedListElement<GeckoChildProcessHost>::removeFrom(
488 *sGeckoChildProcessHosts);
491 void GeckoChildProcessHost::Destroy() {
492 MOZ_RELEASE_ASSERT(!mDestroying);
493 // We can remove from the list before it's really destroyed
494 RemoveFromProcessList();
495 RefPtr<ProcessHandlePromise> whenReady = mHandlePromise;
497 if (!whenReady) {
498 // AsyncLaunch not called yet, so dispatch immediately.
499 whenReady = ProcessHandlePromise::CreateAndReject(
500 LaunchError("DestroyEarly"), __func__);
503 using Value = ProcessHandlePromise::ResolveOrRejectValue;
504 mDestroying = true;
505 whenReady->Then(XRE_GetIOMessageLoop()->SerialEventTarget(), __func__,
506 [this](const Value&) { delete this; });
509 // static
510 mozilla::BinPathType BaseProcessLauncher::GetPathToBinary(
511 FilePath& exePath, GeckoProcessType processType) {
512 BinPathType pathType = XRE_GetChildProcBinPathType(processType);
514 if (pathType == BinPathType::Self) {
515 #if defined(XP_WIN)
516 wchar_t exePathBuf[MAXPATHLEN];
517 if (!::GetModuleFileNameW(nullptr, exePathBuf, MAXPATHLEN)) {
518 MOZ_CRASH("GetModuleFileNameW failed (FIXME)");
520 exePath = FilePath::FromWStringHack(exePathBuf);
521 #else
522 exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
523 #endif
524 return pathType;
527 #ifdef MOZ_WIDGET_COCOA
528 // The GMP child process runs via the Media Plugin Helper executable
529 // which is a clone of plugin-container allowing for GMP-specific
530 // codesigning entitlements.
531 nsCString bundleName;
532 std::string executableLeafName;
533 if (processType == GeckoProcessType_GMPlugin &&
534 mozilla::StaticPrefs::media_plugin_helper_process_enabled()) {
535 bundleName = MOZ_EME_PROCESS_BUNDLENAME;
536 executableLeafName = MOZ_EME_PROCESS_NAME_BRANDED;
537 } else {
538 bundleName = MOZ_CHILD_PROCESS_BUNDLENAME;
539 executableLeafName = MOZ_CHILD_PROCESS_NAME;
541 #endif
543 if (ShouldHaveDirectoryService()) {
544 MOZ_ASSERT(gGREBinPath);
545 #ifdef XP_WIN
546 exePath = FilePath(char16ptr_t(gGREBinPath));
547 #elif MOZ_WIDGET_COCOA
548 nsCOMPtr<nsIFile> childProcPath;
549 NS_NewLocalFile(nsDependentString(gGREBinPath), false,
550 getter_AddRefs(childProcPath));
552 // We need to use an App Bundle on OS X so that we can hide
553 // the dock icon. See Bug 557225.
554 childProcPath->AppendNative(bundleName);
555 childProcPath->AppendNative("Contents"_ns);
556 childProcPath->AppendNative("MacOS"_ns);
557 nsCString tempCPath;
558 childProcPath->GetNativePath(tempCPath);
559 exePath = FilePath(tempCPath.get());
560 #else
561 nsCString path;
562 NS_CopyUnicodeToNative(nsDependentString(gGREBinPath), path);
563 exePath = FilePath(path.get());
564 #endif
567 if (exePath.empty()) {
568 #ifdef XP_WIN
569 exePath =
570 FilePath::FromWStringHack(CommandLine::ForCurrentProcess()->program());
571 #else
572 exePath = FilePath(CommandLine::ForCurrentProcess()->argv()[0]);
573 #endif
574 exePath = exePath.DirName();
577 #ifdef MOZ_WIDGET_COCOA
578 exePath = exePath.Append(executableLeafName);
579 #else
580 exePath = exePath.AppendASCII(MOZ_CHILD_PROCESS_NAME);
581 #endif
583 return pathType;
586 #ifdef MOZ_WIDGET_COCOA
587 class AutoCFTypeObject {
588 public:
589 explicit AutoCFTypeObject(CFTypeRef object) { mObject = object; }
590 ~AutoCFTypeObject() { ::CFRelease(mObject); }
592 private:
593 CFTypeRef mObject;
595 #endif
597 // We start the unique IDs at 1 so that 0 can be used to mean that
598 // a component has no unique ID assigned to it.
599 uint32_t GeckoChildProcessHost::sNextUniqueID = 1;
601 /* static */
602 uint32_t GeckoChildProcessHost::GetUniqueID() { return sNextUniqueID++; }
604 /* static */
605 void GeckoChildProcessHost::SetEnv(const char* aKey, const char* aValue) {
606 MOZ_ASSERT(mLaunchOptions);
607 mLaunchOptions->env_map[ENVIRONMENT_STRING(aKey)] =
608 ENVIRONMENT_STRING(aValue);
611 void GeckoChildProcessHost::PrepareLaunch() {
612 if (CrashReporter::GetEnabled()) {
613 CrashReporter::OOPInit();
616 #if defined(XP_LINUX) && defined(MOZ_SANDBOX)
617 SandboxLaunchPrepare(mProcessType, mLaunchOptions.get(), mSandbox);
618 #endif
620 #ifdef XP_WIN
622 # if defined(MOZ_SANDBOX)
623 // We need to get the pref here as the process is launched off main thread.
624 if (mProcessType == GeckoProcessType_Content) {
625 // Win32k Lockdown state must be initialized on the main thread.
626 // This is our last chance to do it before it is read on the IPC Launch
627 // thread
628 GetWin32kLockdownState();
629 mSandboxLevel = GetEffectiveContentSandboxLevel();
630 mEnableSandboxLogging =
631 Preferences::GetBool("security.sandbox.logging.enabled");
633 // We currently have to whitelist certain paths for tests to work in some
634 // development configurations.
635 nsAutoString readPaths;
636 nsresult rv = Preferences::GetString(
637 "security.sandbox.content.read_path_whitelist", readPaths);
638 if (NS_SUCCEEDED(rv)) {
639 for (const nsAString& readPath : readPaths.Split(',')) {
640 nsString trimmedPath(readPath);
641 trimmedPath.Trim(" ", true, true);
642 std::wstring resolvedPath(trimmedPath.Data());
643 // Check if path ends with '\' as this indicates we want to give read
644 // access to a directory and so it needs a wildcard.
645 if (resolvedPath.back() == L'\\') {
646 resolvedPath.append(L"*");
648 mAllowedFilesRead.push_back(resolvedPath);
652 # endif
654 # if defined(MOZ_SANDBOX)
655 // For other process types we can't rely on them being launched on main
656 // thread and they may not have access to prefs in the child process, so allow
657 // them to turn on logging via an environment variable.
658 mEnableSandboxLogging =
659 mEnableSandboxLogging || !!PR_GetEnv("MOZ_SANDBOX_LOGGING");
661 # endif
662 #elif defined(XP_MACOSX)
663 # if defined(MOZ_SANDBOX)
664 if (ShouldHaveDirectoryService() &&
665 mProcessType != GeckoProcessType_GMPlugin) {
666 mozilla::Unused << NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
667 getter_AddRefs(mProfileDir));
669 # endif
670 #endif
673 #ifdef XP_WIN
674 void GeckoChildProcessHost::InitWindowsGroupID() {
675 // On Win7+, pass the application user model to the child, so it can
676 // register with it. This insures windows created by the container
677 // properly group with the parent app on the Win7 taskbar.
678 nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
679 if (taskbarInfo) {
680 bool isSupported = false;
681 taskbarInfo->GetAvailable(&isSupported);
682 nsAutoString appId;
683 if (isSupported && NS_SUCCEEDED(taskbarInfo->GetDefaultGroupId(appId))) {
684 MOZ_ASSERT(mGroupId.EqualsLiteral("-"));
685 mGroupId.Assign(appId);
689 #endif
691 bool GeckoChildProcessHost::SyncLaunch(std::vector<std::string> aExtraOpts,
692 int aTimeoutMs) {
693 if (!AsyncLaunch(std::move(aExtraOpts))) {
694 return false;
696 return WaitUntilConnected(aTimeoutMs);
699 // Note: for most process types, we currently call AsyncLaunch, and therefore
700 // the *ProcessLauncher constructor, on the main thread, while the
701 // ProcessLauncher methods to actually execute the launch are called on the IO
702 // or IPC launcher thread. GMP processes are an exception - the GMP code
703 // invokes GeckoChildProcessHost from non-main-threads, and therefore we cannot
704 // rely on having access to mainthread-only services (like the directory
705 // service) from this code if we're launching that type of process.
706 bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) {
707 PrepareLaunch();
709 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
710 if (IsMacSandboxLaunchEnabled() && !AppendMacSandboxParams(aExtraOpts)) {
711 return false;
713 #endif
715 RefPtr<BaseProcessLauncher> launcher =
716 new ProcessLauncher(this, std::move(aExtraOpts));
717 #ifdef ALLOW_GECKO_CHILD_PROCESS_ARCH
718 launcher->SetLaunchArchitecture(mLaunchArch);
719 #endif
721 // Note: Destroy() waits on mHandlePromise to delete |this|. As such, we want
722 // to be sure that all of our post-launch processing on |this| happens before
723 // mHandlePromise notifies.
724 MOZ_ASSERT(mHandlePromise == nullptr);
725 mHandlePromise =
726 mozilla::InvokeAsync<GeckoChildProcessHost*>(
727 IOThread(), launcher.get(), __func__, &BaseProcessLauncher::Launch,
728 this)
729 ->Then(
730 IOThread(), __func__,
731 [this](LaunchResults&& aResults) {
734 mozilla::AutoWriteLock handleLock(mHandleLock);
735 if (!OpenPrivilegedHandle(base::GetProcId(aResults.mHandle))
736 #ifdef XP_WIN
737 // If we failed in opening the process handle, try
738 // harder by duplicating one.
739 && !::DuplicateHandle(
740 ::GetCurrentProcess(), aResults.mHandle,
741 ::GetCurrentProcess(), &mChildProcessHandle,
742 PROCESS_DUP_HANDLE | PROCESS_TERMINATE |
743 PROCESS_QUERY_INFORMATION | PROCESS_VM_READ |
744 SYNCHRONIZE,
745 FALSE, 0)
746 #endif // XP_WIN
748 MOZ_CRASH("cannot open handle to child process");
750 // The original handle is no longer needed; it must
751 // be closed to prevent a resource leak.
752 base::CloseProcessHandle(aResults.mHandle);
753 // FIXME (bug 1720523): define a cross-platform
754 // "safe" invalid value to use in places like this.
755 aResults.mHandle = 0;
757 #ifdef XP_MACOSX
758 this->mChildTask = aResults.mChildTask;
759 #endif
761 if (mNodeChannel) {
762 mNodeChannel->SetOtherPid(
763 base::GetProcId(this->mChildProcessHandle));
764 #ifdef XP_MACOSX
765 mNodeChannel->SetMachTaskPort(this->mChildTask);
766 #endif
769 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
770 this->mSandboxBroker = std::move(aResults.mSandboxBroker);
771 #endif
773 MonitorAutoLock lock(mMonitor);
774 // The OnChannel{Connected,Error} may have already advanced
775 // the state.
776 if (mProcessState < PROCESS_CREATED) {
777 mProcessState = PROCESS_CREATED;
779 lock.Notify();
781 return ProcessHandlePromise::CreateAndResolve(
782 GetChildProcessHandle(), __func__);
784 [this](const LaunchError aError) {
785 // WaitUntilConnected might be waiting for us to signal.
786 // If something failed let's set the error state and notify.
787 CHROMIUM_LOG(ERROR)
788 << "Failed to launch "
789 << XRE_GeckoProcessTypeToString(mProcessType)
790 << " subprocess";
791 Telemetry::Accumulate(
792 Telemetry::SUBPROCESS_LAUNCH_FAILURE,
793 nsDependentCString(
794 XRE_GeckoProcessTypeToString(mProcessType)));
795 nsCString telemetryKey = nsPrintfCString(
796 #if defined(XP_WIN)
797 "%s,0x%lx,%s",
798 #else
799 "%s,%d,%s",
800 #endif
801 aError.FunctionName(), aError.ErrorCode(),
802 XRE_GeckoProcessTypeToString(mProcessType));
803 // Max telemetry key is 72 chars
804 // https://searchfox.org/mozilla-central/rev/c244b16815d1fc827d141472b9faac5610f250e7/toolkit/components/telemetry/core/TelemetryScalar.cpp#105
805 if (telemetryKey.Length() > 72) {
806 NS_WARNING(nsPrintfCString("Truncating telemetry key: %s",
807 telemetryKey.get())
808 .get());
809 telemetryKey.Truncate(72);
811 Telemetry::ScalarAdd(
812 Telemetry::ScalarID::
813 DOM_PARENTPROCESS_PROCESS_LAUNCH_ERRORS,
814 NS_ConvertUTF8toUTF16(telemetryKey), 1);
816 MonitorAutoLock lock(mMonitor);
817 mProcessState = PROCESS_ERROR;
818 lock.Notify();
820 return ProcessHandlePromise::CreateAndReject(aError, __func__);
822 return true;
825 bool GeckoChildProcessHost::WaitUntilConnected(int32_t aTimeoutMs) {
826 AUTO_PROFILER_LABEL("GeckoChildProcessHost::WaitUntilConnected", OTHER);
828 // NB: this uses a different mechanism than the chromium parent
829 // class.
830 TimeDuration timeout = (aTimeoutMs > 0)
831 ? TimeDuration::FromMilliseconds(aTimeoutMs)
832 : TimeDuration::Forever();
834 MonitorAutoLock lock(mMonitor);
835 TimeStamp waitStart = TimeStamp::Now();
836 TimeStamp current;
838 // We'll receive several notifications, we need to exit when we
839 // have either successfully launched or have timed out.
840 while (mProcessState != PROCESS_CONNECTED) {
841 // If there was an error then return it, don't wait out the timeout.
842 if (mProcessState == PROCESS_ERROR) {
843 break;
846 CVStatus status = lock.Wait(timeout);
847 if (status == CVStatus::Timeout) {
848 break;
851 if (timeout != TimeDuration::Forever()) {
852 current = TimeStamp::Now();
853 timeout -= current - waitStart;
854 waitStart = current;
858 return mProcessState == PROCESS_CONNECTED;
861 bool GeckoChildProcessHost::WaitForProcessHandle() {
862 MonitorAutoLock lock(mMonitor);
863 while (mProcessState < PROCESS_CREATED) {
864 lock.Wait();
866 MOZ_ASSERT(mProcessState == PROCESS_ERROR || GetChildProcessHandle());
868 return mProcessState < PROCESS_ERROR;
871 bool GeckoChildProcessHost::LaunchAndWaitForProcessHandle(
872 StringVector aExtraOpts) {
873 if (!AsyncLaunch(std::move(aExtraOpts))) {
874 return false;
876 return WaitForProcessHandle();
879 void GeckoChildProcessHost::InitializeChannel(
880 IPC::Channel::ChannelHandle&& aServerHandle) {
881 // Create the IPC channel which will be used for communication with this
882 // process.
883 mozilla::UniquePtr<IPC::Channel> channel = MakeUnique<IPC::Channel>(
884 std::move(aServerHandle), IPC::Channel::MODE_SERVER,
885 base::kInvalidProcessId);
886 #if defined(XP_WIN)
887 channel->StartAcceptingHandles(IPC::Channel::MODE_SERVER);
888 #elif defined(XP_DARWIN)
889 channel->StartAcceptingMachPorts(IPC::Channel::MODE_SERVER);
890 #endif
892 mNodeController = NodeController::GetSingleton();
893 std::tie(mInitialPort, mNodeChannel) =
894 mNodeController->InviteChildProcess(std::move(channel), this);
896 MonitorAutoLock lock(mMonitor);
897 mProcessState = CHANNEL_INITIALIZED;
898 lock.Notify();
901 void GeckoChildProcessHost::SetAlreadyDead() {
902 mozilla::AutoWriteLock handleLock(mHandleLock);
903 if (mChildProcessHandle &&
904 mChildProcessHandle != base::kInvalidProcessHandle) {
905 base::CloseProcessHandle(mChildProcessHandle);
908 mChildProcessHandle = 0;
911 void BaseProcessLauncher::GetChildLogName(const char* origLogName,
912 nsACString& buffer) {
913 #ifdef XP_WIN
914 // On Windows we must expand relative paths because sandboxing rules
915 // bound only to full paths. fopen fowards to NtCreateFile which checks
916 // the path against the sanboxing rules as passed to fopen (left relative).
917 char absPath[MAX_PATH + 2];
918 if (_fullpath(absPath, origLogName, sizeof(absPath))) {
919 buffer.Append(absPath);
920 } else
921 #endif
923 buffer.Append(origLogName);
926 // Remove .moz_log extension to avoid its duplication, it will be added
927 // automatically by the logging backend
928 static constexpr auto kMozLogExt = nsLiteralCString{MOZ_LOG_FILE_EXTENSION};
929 if (StringEndsWith(buffer, kMozLogExt)) {
930 buffer.Truncate(buffer.Length() - kMozLogExt.Length());
933 // Append child-specific postfix to name
934 buffer.AppendLiteral(".child-");
935 buffer.AppendInt(mChildId);
938 // Windows needs a single dedicated thread for process launching,
939 // because of thread-safety restrictions/assertions in the sandbox
940 // code.
942 // Android also needs a single dedicated thread to simplify thread
943 // safety in java.
945 // Fork server needs a dedicated thread for accessing
946 // |ForkServiceChild|.
947 #if defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) || \
948 defined(MOZ_ENABLE_FORKSERVER)
950 static mozilla::StaticMutex gIPCLaunchThreadMutex;
951 static mozilla::StaticRefPtr<nsIThread> gIPCLaunchThread
952 MOZ_GUARDED_BY(gIPCLaunchThreadMutex);
954 class IPCLaunchThreadObserver final : public nsIObserver {
955 public:
956 NS_DECL_ISUPPORTS
957 NS_DECL_NSIOBSERVER
958 protected:
959 virtual ~IPCLaunchThreadObserver() = default;
962 NS_IMPL_ISUPPORTS(IPCLaunchThreadObserver, nsIObserver, nsISupports)
964 NS_IMETHODIMP
965 IPCLaunchThreadObserver::Observe(nsISupports* aSubject, const char* aTopic,
966 const char16_t* aData) {
967 MOZ_RELEASE_ASSERT(strcmp(aTopic, "xpcom-shutdown-threads") == 0);
968 StaticMutexAutoLock lock(gIPCLaunchThreadMutex);
970 nsresult rv = NS_OK;
971 if (gIPCLaunchThread) {
972 rv = gIPCLaunchThread->Shutdown();
973 gIPCLaunchThread = nullptr;
975 mozilla::Unused << NS_WARN_IF(NS_FAILED(rv));
976 return rv;
979 nsCOMPtr<nsIEventTarget> GetIPCLauncher() {
980 StaticMutexAutoLock lock(gIPCLaunchThreadMutex);
981 if (!gIPCLaunchThread) {
982 nsCOMPtr<nsIThread> thread;
983 nsresult rv = NS_NewNamedThread("IPC Launch"_ns, getter_AddRefs(thread));
984 if (!NS_WARN_IF(NS_FAILED(rv))) {
985 NS_DispatchToMainThread(
986 NS_NewRunnableFunction("GeckoChildProcessHost::GetIPCLauncher", [] {
987 nsCOMPtr<nsIObserverService> obsService =
988 mozilla::services::GetObserverService();
989 nsCOMPtr<nsIObserver> obs = new IPCLaunchThreadObserver();
990 obsService->AddObserver(obs, "xpcom-shutdown-threads", false);
991 }));
992 gIPCLaunchThread = thread.forget();
996 nsCOMPtr<nsIEventTarget> thread = gIPCLaunchThread.get();
997 MOZ_DIAGNOSTIC_ASSERT(thread);
998 return thread;
1001 #else // defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID) ||
1002 // defined(MOZ_ENABLE_FORKSERVER)
1004 // Other platforms use an on-demand thread pool.
1006 nsCOMPtr<nsIEventTarget> GetIPCLauncher() {
1007 nsCOMPtr<nsIEventTarget> pool =
1008 mozilla::SharedThreadPool::Get("IPC Launch"_ns);
1009 MOZ_DIAGNOSTIC_ASSERT(pool);
1010 return pool;
1013 #endif // XP_WIN || MOZ_WIDGET_ANDROID || MOZ_ENABLE_FORKSERVER
1015 void
1016 #if defined(XP_WIN)
1017 AddAppDirToCommandLine(CommandLine& aCmdLine, nsIFile* aAppDir)
1018 #else
1019 AddAppDirToCommandLine(std::vector<std::string>& aCmdLine, nsIFile* aAppDir,
1020 nsIFile* aProfileDir)
1021 #endif
1023 // Content processes need access to application resources, so pass
1024 // the full application directory path to the child process.
1025 if (aAppDir) {
1026 #if defined(XP_WIN)
1027 nsString path;
1028 MOZ_ALWAYS_SUCCEEDS(aAppDir->GetPath(path));
1029 aCmdLine.AppendLooseValue(UTF8ToWide(geckoargs::sAppDir.Name()));
1030 std::wstring wpath(path.get());
1031 aCmdLine.AppendLooseValue(wpath);
1032 #else
1033 nsAutoCString path;
1034 MOZ_ALWAYS_SUCCEEDS(aAppDir->GetNativePath(path));
1035 geckoargs::sAppDir.Put(path.get(), aCmdLine);
1036 #endif
1038 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1039 // Full path to the profile dir
1040 if (aProfileDir) {
1041 // If the profile doesn't exist, normalization will
1042 // fail. But we don't return an error here because some
1043 // tests require startup with a missing profile dir.
1044 // For users, almost universally, the profile will be in
1045 // the home directory and normalization isn't required.
1046 mozilla::Unused << aProfileDir->Normalize();
1047 nsAutoCString path;
1048 MOZ_ALWAYS_SUCCEEDS(aProfileDir->GetNativePath(path));
1049 geckoargs::sProfile.Put(path.get(), aCmdLine);
1051 #endif
1055 #if defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
1056 static bool Contains(const std::vector<std::string>& aExtraOpts,
1057 const char* aValue) {
1058 return std::any_of(aExtraOpts.begin(), aExtraOpts.end(),
1059 [&](const std::string arg) {
1060 return arg.find(aValue) != std::string::npos;
1063 #endif // defined(XP_WIN) && (defined(MOZ_SANDBOX) || defined(_ARM64_))
1065 RefPtr<ProcessLaunchPromise> BaseProcessLauncher::PerformAsyncLaunch() {
1066 Result<Ok, LaunchError> aError = DoSetup();
1067 if (aError.isErr()) {
1068 return ProcessLaunchPromise::CreateAndReject(aError.unwrapErr(), __func__);
1070 RefPtr<BaseProcessLauncher> self = this;
1071 return DoLaunch()->Then(
1072 mLaunchThread, __func__,
1073 [self](base::ProcessHandle aHandle) {
1074 self->mResults.mHandle = aHandle;
1075 return self->FinishLaunch();
1077 [](LaunchError aError) {
1078 return ProcessLaunchPromise::CreateAndReject(aError, __func__);
1082 Result<Ok, LaunchError> BaseProcessLauncher::DoSetup() {
1083 RefPtr<BaseProcessLauncher> self = this;
1084 GetProfilerEnvVarsForChildProcess([self](const char* key, const char* value) {
1085 self->mLaunchOptions->env_map[ENVIRONMENT_STRING(key)] =
1086 ENVIRONMENT_STRING(value);
1088 #ifdef MOZ_MEMORY
1089 if (mProcessType == GeckoProcessType_Content) {
1090 nsAutoCString mallocOpts(PR_GetEnv("MALLOC_OPTIONS"));
1091 // Disable randomization of small arenas in content.
1092 mallocOpts.Append("r");
1093 self->mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MALLOC_OPTIONS")] =
1094 ENVIRONMENT_STRING(mallocOpts.get());
1096 #endif
1098 MapChildLogging();
1100 return Ok();
1103 void BaseProcessLauncher::MapChildLogging() {
1104 const char* origNSPRLogName = PR_GetEnv("NSPR_LOG_FILE");
1105 const char* origMozLogName = PR_GetEnv("MOZ_LOG_FILE");
1107 if (origNSPRLogName) {
1108 nsAutoCString nsprLogName;
1109 GetChildLogName(origNSPRLogName, nsprLogName);
1110 mLaunchOptions->env_map[ENVIRONMENT_LITERAL("NSPR_LOG_FILE")] =
1111 ENVIRONMENT_STRING(nsprLogName.get());
1113 if (origMozLogName) {
1114 nsAutoCString mozLogName;
1115 GetChildLogName(origMozLogName, mozLogName);
1116 mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MOZ_LOG_FILE")] =
1117 ENVIRONMENT_STRING(mozLogName.get());
1120 // `RUST_LOG_CHILD` is meant for logging child processes only.
1121 nsAutoCString childRustLog(PR_GetEnv("RUST_LOG_CHILD"));
1122 if (!childRustLog.IsEmpty()) {
1123 mLaunchOptions->env_map[ENVIRONMENT_LITERAL("RUST_LOG")] =
1124 ENVIRONMENT_STRING(childRustLog.get());
1128 Result<Ok, LaunchError> BaseProcessLauncher::DoFinishLaunch() {
1129 // We're in the parent and the child was launched. Close the child channel
1130 // handle in the parent as soon as possible, which will allow the parent to
1131 // detect when the child closes its handle (either due to normal exit or due
1132 // to crash).
1133 mClientChannelHandle = nullptr;
1135 return Ok();
1138 #if defined(MOZ_WIDGET_GTK)
1139 Result<Ok, LaunchError> LinuxProcessLauncher::DoSetup() {
1140 Result<Ok, LaunchError> aError = PosixProcessLauncher::DoSetup();
1141 if (aError.isErr()) {
1142 return aError;
1145 if (mProcessType == GeckoProcessType_Content) {
1146 // disable IM module to avoid sandbox violation
1147 mLaunchOptions->env_map["GTK_IM_MODULE"] = "gtk-im-context-simple";
1149 // Disable ATK accessibility code in content processes because it conflicts
1150 // with the sandbox, and we proxy that information through the main process
1151 // anyway.
1152 mLaunchOptions->env_map["NO_AT_BRIDGE"] = "1";
1155 # ifdef MOZ_SANDBOX
1156 if (!mTmpDirName.IsEmpty()) {
1157 // Point a bunch of things that might want to write from content to our
1158 // shiny new content-process specific tmpdir
1159 mLaunchOptions->env_map[ENVIRONMENT_LITERAL("TMPDIR")] =
1160 ENVIRONMENT_STRING(mTmpDirName.get());
1161 // Partial fix for bug 1380051 (not persistent - should be)
1162 mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MESA_GLSL_CACHE_DIR")] =
1163 ENVIRONMENT_STRING(mTmpDirName.get());
1165 # endif // MOZ_SANDBOX
1167 return Ok();
1169 #endif // MOZ_WIDGET_GTK
1171 #ifdef XP_UNIX
1172 Result<Ok, LaunchError> PosixProcessLauncher::DoSetup() {
1173 Result<Ok, LaunchError> aError = BaseProcessLauncher::DoSetup();
1174 if (aError.isErr()) {
1175 return aError;
1178 // XPCOM may not be initialized in some subprocesses. We don't want
1179 // to initialize XPCOM just for the directory service, especially
1180 // since LD_LIBRARY_PATH is already set correctly in subprocesses
1181 // (meaning that we don't need to set that up in the environment).
1182 if (ShouldHaveDirectoryService()) {
1183 MOZ_ASSERT(gGREBinPath);
1184 nsCString path;
1185 NS_CopyUnicodeToNative(nsDependentString(gGREBinPath), path);
1186 # if defined(XP_LINUX) || defined(__DragonFly__) || defined(XP_FREEBSD) || \
1187 defined(XP_NETBSD) || defined(XP_OPENBSD)
1188 const char* ld_library_path = PR_GetEnv("LD_LIBRARY_PATH");
1189 nsCString new_ld_lib_path(path.get());
1191 if (ld_library_path && *ld_library_path) {
1192 new_ld_lib_path.Append(':');
1193 new_ld_lib_path.Append(ld_library_path);
1195 mLaunchOptions->env_map["LD_LIBRARY_PATH"] = new_ld_lib_path.get();
1197 # elif XP_DARWIN
1198 // With signed production Mac builds, the dynamic linker (dyld) will
1199 // ignore dyld environment variables preventing the use of variables
1200 // such as DYLD_LIBRARY_PATH and DYLD_INSERT_LIBRARIES.
1202 // If we're running with gtests, add the gtest XUL ahead of normal XUL on
1203 // the DYLD_LIBRARY_PATH so that plugin-container.app loads it instead.
1204 nsCString new_dyld_lib_path(path.get());
1205 if (PR_GetEnv("MOZ_RUN_GTEST")) {
1206 new_dyld_lib_path = path + "/gtest:"_ns + new_dyld_lib_path;
1207 mLaunchOptions->env_map["DYLD_LIBRARY_PATH"] = new_dyld_lib_path.get();
1210 // DYLD_INSERT_LIBRARIES is currently unused by default but we allow
1211 // it to be set by the external environment.
1212 const char* interpose = PR_GetEnv("DYLD_INSERT_LIBRARIES");
1213 if (interpose && strlen(interpose) > 0) {
1214 mLaunchOptions->env_map["DYLD_INSERT_LIBRARIES"] = interpose;
1217 // Prevent connection attempts to diagnosticd(8) to save cycles. Log
1218 // messages can trigger these connection attempts, but access to
1219 // diagnosticd is blocked in sandboxed child processes.
1220 # ifdef MOZ_SANDBOX
1221 if (mDisableOSActivityMode) {
1222 mLaunchOptions->env_map["OS_ACTIVITY_MODE"] = "disable";
1224 # endif // defined(MOZ_SANDBOX)
1225 # endif
1228 FilePath exePath;
1229 BinPathType pathType = GetPathToBinary(exePath, mProcessType);
1231 // remap the IPC socket fd to a well-known int, as the OS does for
1232 // STDOUT_FILENO, for example
1233 // The fork server doesn't use IPC::Channel, so can skip this step.
1234 if (mProcessType != GeckoProcessType_ForkServer) {
1235 # ifdef MOZ_WIDGET_ANDROID
1236 // On Android mChannelDstFd is uninitialised and the launching code uses
1237 // only the first of each pair.
1238 mLaunchOptions->fds_to_remap.push_back(
1239 std::pair<int, int>(mClientChannelHandle.get(), -1));
1240 # else
1241 MOZ_ASSERT(mChannelDstFd >= 0);
1242 mLaunchOptions->fds_to_remap.push_back(
1243 std::pair<int, int>(mClientChannelHandle.get(), mChannelDstFd));
1244 # endif
1247 // no need for kProcessChannelID, the child process inherits the
1248 // other end of the socketpair() from us
1250 mChildArgv.push_back(exePath.value());
1252 if (pathType == BinPathType::Self) {
1253 mChildArgv.push_back("-contentproc");
1256 mChildArgv.insert(mChildArgv.end(), mExtraOpts.begin(), mExtraOpts.end());
1258 if ((mProcessType == GeckoProcessType_Content ||
1259 mProcessType == GeckoProcessType_ForkServer) &&
1260 Omnijar::IsInitialized()) {
1261 // Make sure that child processes can find the omnijar, if they
1262 // use full XPCOM. See Omnijar::ChildProcessInit and its callers.
1263 nsAutoCString path;
1264 nsCOMPtr<nsIFile> greFile = Omnijar::GetPath(Omnijar::GRE);
1265 if (greFile && NS_SUCCEEDED(greFile->GetNativePath(path))) {
1266 geckoargs::sGREOmni.Put(path.get(), mChildArgv);
1268 nsCOMPtr<nsIFile> appFile = Omnijar::GetPath(Omnijar::APP);
1269 if (appFile && NS_SUCCEEDED(appFile->GetNativePath(path))) {
1270 geckoargs::sAppOmni.Put(path.get(), mChildArgv);
1274 if (mProcessType != GeckoProcessType_GMPlugin) {
1275 // Add the application directory path (-appdir path)
1276 # ifdef XP_MACOSX
1277 AddAppDirToCommandLine(mChildArgv, mAppDir, mProfileDir);
1278 # else
1279 AddAppDirToCommandLine(mChildArgv, mAppDir, nullptr);
1280 # endif
1283 mChildArgv.push_back(mInitialChannelIdString);
1285 mChildArgv.push_back(mPidString);
1287 if (!CrashReporter::IsDummy()) {
1288 # if defined(MOZ_WIDGET_COCOA)
1289 mChildArgv.push_back(CrashReporter::GetChildNotificationPipe());
1290 # elif defined(XP_UNIX)
1291 int childCrashFd, childCrashRemapFd;
1292 if (NS_WARN_IF(!CrashReporter::CreateNotificationPipeForChild(
1293 &childCrashFd, &childCrashRemapFd))) {
1294 return Err(LaunchError("CR::CreateNotificationPipeForChild"));
1297 if (0 <= childCrashFd) {
1298 mLaunchOptions->fds_to_remap.push_back(
1299 std::pair<int, int>(childCrashFd, childCrashRemapFd));
1300 // "true" == crash reporting enabled
1301 mChildArgv.push_back("true");
1302 } else {
1303 // "false" == crash reporting disabled
1304 mChildArgv.push_back("false");
1306 # endif
1309 # ifdef MOZ_WIDGET_COCOA
1311 auto* thisMac = static_cast<MacProcessLauncher*>(this);
1312 kern_return_t kr =
1313 bootstrap_check_in(bootstrap_port, thisMac->mMachConnectionName.c_str(),
1314 getter_Transfers(thisMac->mParentRecvPort));
1315 if (kr != KERN_SUCCESS) {
1316 CHROMIUM_LOG(ERROR) << "parent bootstrap_check_in failed: "
1317 << mach_error_string(kr);
1318 return Err(LaunchError("bootstrap_check_in", kr));
1320 mChildArgv.push_back(thisMac->mMachConnectionName.c_str());
1322 # endif // MOZ_WIDGET_COCOA
1324 mChildArgv.push_back(ChildProcessType());
1325 return Ok();
1327 #endif // XP_UNIX
1329 #if defined(MOZ_WIDGET_ANDROID)
1330 RefPtr<ProcessHandlePromise> AndroidProcessLauncher::DoLaunch() {
1331 return LaunchAndroidService(mProcessType, mChildArgv,
1332 mLaunchOptions->fds_to_remap);
1334 #endif // MOZ_WIDGET_ANDROID
1336 #ifdef XP_UNIX
1337 RefPtr<ProcessHandlePromise> PosixProcessLauncher::DoLaunch() {
1338 ProcessHandle handle = 0;
1339 Result<Ok, LaunchError> aError =
1340 base::LaunchApp(mChildArgv, *mLaunchOptions, &handle);
1341 if (aError.isErr()) {
1342 return ProcessHandlePromise::CreateAndReject(aError.unwrapErr(), __func__);
1344 return ProcessHandlePromise::CreateAndResolve(handle, __func__);
1346 #endif // XP_UNIX
1348 #ifdef XP_MACOSX
1349 Result<Ok, LaunchError> MacProcessLauncher::DoFinishLaunch() {
1350 Result<Ok, LaunchError> aError = PosixProcessLauncher::DoFinishLaunch();
1351 if (aError.isErr()) {
1352 return aError;
1355 MOZ_ASSERT(mParentRecvPort, "should have been configured during DoSetup()");
1357 // Wait for the child process to send us its 'task_t' data.
1358 const int kTimeoutMs = 10000;
1360 mozilla::UniqueMachSendRight child_task;
1361 audit_token_t audit_token{};
1362 kern_return_t kr = MachReceivePortSendRight(
1363 mParentRecvPort, mozilla::Some(kTimeoutMs), &child_task, &audit_token);
1364 if (kr != KERN_SUCCESS) {
1365 std::string errString = StringPrintf("0x%x %s", kr, mach_error_string(kr));
1366 CHROMIUM_LOG(ERROR) << "parent MachReceivePortSendRight failed: "
1367 << errString;
1368 return Err(LaunchError("MachReceivePortSendRight", kr));
1371 // Ensure the message was sent by the newly spawned child process.
1372 if (audit_token_to_pid(audit_token) != base::GetProcId(mResults.mHandle)) {
1373 CHROMIUM_LOG(ERROR) << "task_t was not sent by child process";
1374 return Err(LaunchError("audit_token_to_pid"));
1377 // Ensure the task_t corresponds to the newly spawned child process.
1378 pid_t task_pid = -1;
1379 kr = pid_for_task(child_task.get(), &task_pid);
1380 if (kr != KERN_SUCCESS) {
1381 CHROMIUM_LOG(ERROR) << "pid_for_task failed: " << mach_error_string(kr);
1382 return Err(LaunchError("pid_for_task", kr));
1384 if (task_pid != base::GetProcId(mResults.mHandle)) {
1385 CHROMIUM_LOG(ERROR) << "task_t is not for child process";
1386 return Err(LaunchError("task_pid"));
1389 mResults.mChildTask = child_task.release();
1391 return Ok();
1393 #endif // XP_MACOSX
1395 #ifdef XP_WIN
1396 Result<Ok, LaunchError> WindowsProcessLauncher::DoSetup() {
1397 Result<Ok, LaunchError> aError = BaseProcessLauncher::DoSetup();
1398 if (aError.isErr()) {
1399 return aError;
1402 FilePath exePath;
1403 BinPathType pathType = GetPathToBinary(exePath, mProcessType);
1405 # if defined(MOZ_SANDBOX) || defined(_ARM64_)
1406 const bool isGMP = mProcessType == GeckoProcessType_GMPlugin;
1407 const bool isWidevine = isGMP && Contains(mExtraOpts, "gmp-widevinecdm");
1408 # if defined(_ARM64_)
1409 bool useRemoteSandboxBroker = false;
1410 if (mLaunchArch & (base::PROCESS_ARCH_I386 | base::PROCESS_ARCH_X86_64)) {
1411 // On Windows on ARM64 for ClearKey and Widevine, and for the sandbox
1412 // launcher process, we want to run the x86 plugin-container.exe in
1413 // the "i686" subdirectory, instead of the aarch64 plugin-container.exe.
1414 // So insert "i686" into the exePath.
1415 exePath = exePath.DirName().AppendASCII("i686").Append(exePath.BaseName());
1416 useRemoteSandboxBroker =
1417 mProcessType != GeckoProcessType_RemoteSandboxBroker;
1419 # endif // if defined(_ARM64_)
1420 # endif // defined(MOZ_SANDBOX) || defined(_ARM64_)
1422 mCmdLine.emplace(exePath.ToWStringHack());
1424 if (pathType == BinPathType::Self) {
1425 mCmdLine->AppendLooseValue(UTF8ToWide("-contentproc"));
1428 # ifdef HAS_DLL_BLOCKLIST
1429 if (IsDynamicBlocklistDisabled(
1430 gSafeMode,
1431 CommandLine::ForCurrentProcess()->HasSwitch(UTF8ToWide(
1432 mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch)))) {
1433 mCmdLine->AppendLooseValue(
1434 UTF8ToWide(mozilla::geckoargs::sDisableDynamicDllBlocklist.sMatch));
1436 # endif // HAS_DLL_BLOCKLIST
1438 // Inherit the initial client channel handle into the child process.
1439 std::wstring processChannelID =
1440 std::to_wstring(uint32_t(uintptr_t(mClientChannelHandle.get())));
1441 mLaunchOptions->handles_to_inherit.push_back(mClientChannelHandle.get());
1442 mCmdLine->AppendSwitchWithValue(switches::kProcessChannelID,
1443 processChannelID);
1445 for (std::vector<std::string>::iterator it = mExtraOpts.begin();
1446 it != mExtraOpts.end(); ++it) {
1447 mCmdLine->AppendLooseValue(UTF8ToWide(*it));
1450 # if defined(MOZ_SANDBOX)
1451 # if defined(_ARM64_)
1452 if (useRemoteSandboxBroker)
1453 mResults.mSandboxBroker = new RemoteSandboxBroker(mLaunchArch);
1454 else
1455 # endif // if defined(_ARM64_)
1456 mResults.mSandboxBroker = new SandboxBroker();
1458 // XXX: Bug 1124167: We should get rid of the process specific logic for
1459 // sandboxing in this class at some point. Unfortunately it will take a bit
1460 // of reorganizing so I don't think this patch is the right time.
1461 switch (mProcessType) {
1462 case GeckoProcessType_Content:
1463 if (mSandboxLevel > 0) {
1464 // For now we treat every failure as fatal in
1465 // SetSecurityLevelForContentProcess and just crash there right away.
1466 // Should this change in the future then we should also handle the error
1467 // here.
1468 mResults.mSandboxBroker->SetSecurityLevelForContentProcess(
1469 mSandboxLevel, mIsFileContent);
1470 mUseSandbox = true;
1472 break;
1473 case GeckoProcessType_IPDLUnitTest:
1474 // XXX: We don't sandbox this process type yet
1475 break;
1476 case GeckoProcessType_GMPlugin:
1477 if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
1478 // The Widevine CDM on Windows can only load at USER_RESTRICTED,
1479 // not at USER_LOCKDOWN. So look in the command line arguments
1480 // to see if we're loading the path to the Widevine CDM, and if
1481 // so use sandbox level USER_RESTRICTED instead of USER_LOCKDOWN.
1482 auto level =
1483 isWidevine ? SandboxBroker::Restricted : SandboxBroker::LockDown;
1484 if (NS_WARN_IF(
1485 !mResults.mSandboxBroker->SetSecurityLevelForGMPlugin(level))) {
1486 return Err(LaunchError("SetSecurityLevelForGMPlugin"));
1488 mUseSandbox = true;
1490 break;
1491 case GeckoProcessType_GPU:
1492 if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_GPU_SANDBOX")) {
1493 // For now we treat every failure as fatal in
1494 // SetSecurityLevelForGPUProcess and just crash there right away. Should
1495 // this change in the future then we should also handle the error here.
1496 mResults.mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel);
1497 mUseSandbox = true;
1499 break;
1500 case GeckoProcessType_VR:
1501 if (mSandboxLevel > 0 && !PR_GetEnv("MOZ_DISABLE_VR_SANDBOX")) {
1502 // TODO: Implement sandbox for VR process, Bug 1430043.
1504 break;
1505 case GeckoProcessType_RDD:
1506 if (!PR_GetEnv("MOZ_DISABLE_RDD_SANDBOX")) {
1507 if (NS_WARN_IF(
1508 !mResults.mSandboxBroker->SetSecurityLevelForRDDProcess())) {
1509 return Err(LaunchError("SetSecurityLevelForRDDProcess"));
1511 mUseSandbox = true;
1513 break;
1514 case GeckoProcessType_Socket:
1515 if (!PR_GetEnv("MOZ_DISABLE_SOCKET_PROCESS_SANDBOX")) {
1516 if (NS_WARN_IF(
1517 !mResults.mSandboxBroker->SetSecurityLevelForSocketProcess())) {
1518 return Err(LaunchError("SetSecurityLevelForSocketProcess"));
1520 mUseSandbox = true;
1522 break;
1523 case GeckoProcessType_Utility:
1524 if (IsUtilitySandboxEnabled(mSandbox)) {
1525 if (!mResults.mSandboxBroker->SetSecurityLevelForUtilityProcess(
1526 mSandbox)) {
1527 return Err(LaunchError("SetSecurityLevelForUtilityProcess"));
1529 mUseSandbox = true;
1531 break;
1532 case GeckoProcessType_RemoteSandboxBroker:
1533 // We don't sandbox the sandbox launcher...
1534 break;
1535 case GeckoProcessType_Default:
1536 default:
1537 MOZ_CRASH("Bad process type in GeckoChildProcessHost");
1538 break;
1541 if (mUseSandbox) {
1542 for (auto it = mAllowedFilesRead.begin(); it != mAllowedFilesRead.end();
1543 ++it) {
1544 mResults.mSandboxBroker->AllowReadFile(it->c_str());
1547 if (mResults.mSandboxBroker->IsWin32kLockedDown()) {
1548 mCmdLine->AppendLooseValue(
1549 UTF8ToWide(geckoargs::sWin32kLockedDown.Name()));
1552 # endif // defined(MOZ_SANDBOX)
1554 // Add the application directory path (-appdir path)
1555 AddAppDirToCommandLine(mCmdLine.ref(), mAppDir);
1557 // XXX Command line params past this point are expected to be at
1558 // the end of the command line string, and in a specific order.
1559 // See XRE_InitChildProcess in nsEmbedFunction.
1561 // Win app model id
1562 mCmdLine->AppendLooseValue(mGroupId.get());
1564 // Initial MessageChannel id
1565 mCmdLine->AppendLooseValue(UTF8ToWide(mInitialChannelIdString));
1567 // Process id
1568 mCmdLine->AppendLooseValue(UTF8ToWide(mPidString));
1570 mCmdLine->AppendLooseValue(
1571 UTF8ToWide(CrashReporter::GetChildNotificationPipe()));
1573 if (!CrashReporter::IsDummy()) {
1574 char werDataAddress[17] = {};
1575 SprintfLiteral(werDataAddress, "%p", mWerDataPointer);
1576 mCmdLine->AppendLooseValue(UTF8ToWide(werDataAddress));
1579 // Process type
1580 mCmdLine->AppendLooseValue(UTF8ToWide(ChildProcessType()));
1582 # ifdef MOZ_SANDBOX
1583 if (mUseSandbox) {
1584 // Mark the handles to inherit as inheritable.
1585 for (HANDLE h : mLaunchOptions->handles_to_inherit) {
1586 mResults.mSandboxBroker->AddHandleToShare(h);
1589 # endif // MOZ_SANDBOX
1591 return Ok();
1594 RefPtr<ProcessHandlePromise> WindowsProcessLauncher::DoLaunch() {
1595 ProcessHandle handle = 0;
1596 # ifdef MOZ_SANDBOX
1597 if (mUseSandbox) {
1598 const IMAGE_THUNK_DATA* cachedNtdllThunk =
1599 mCachedNtdllThunk ? mCachedNtdllThunk->begin() : nullptr;
1600 Result<Ok, LaunchError> err = mResults.mSandboxBroker->LaunchApp(
1601 mCmdLine->program().c_str(), mCmdLine->command_line_string().c_str(),
1602 mLaunchOptions->env_map, mProcessType, mEnableSandboxLogging,
1603 cachedNtdllThunk, &handle);
1604 if (err.isOk()) {
1605 EnvironmentLog("MOZ_PROCESS_LOG")
1606 .print("==> process %d launched child process %d (%S)\n",
1607 base::GetCurrentProcId(), base::GetProcId(handle),
1608 mCmdLine->command_line_string().c_str());
1609 return ProcessHandlePromise::CreateAndResolve(handle, __func__);
1611 return ProcessHandlePromise::CreateAndReject(err.unwrapErr(), __func__);
1613 # endif // defined(MOZ_SANDBOX)
1615 Result<Ok, LaunchError> launchErr =
1616 base::LaunchApp(mCmdLine.ref(), *mLaunchOptions, &handle);
1617 if (launchErr.isErr()) {
1618 return ProcessHandlePromise::CreateAndReject(launchErr.unwrapErr(),
1619 __func__);
1621 return ProcessHandlePromise::CreateAndResolve(handle, __func__);
1624 Result<Ok, LaunchError> WindowsProcessLauncher::DoFinishLaunch() {
1625 Result<Ok, LaunchError> err = BaseProcessLauncher::DoFinishLaunch();
1626 if (err.isErr()) {
1627 return err;
1630 # ifdef MOZ_SANDBOX
1631 if (!mUseSandbox) {
1632 // We need to be able to duplicate handles to some types of non-sandboxed
1633 // child processes.
1634 switch (mProcessType) {
1635 case GeckoProcessType_Default:
1636 MOZ_CRASH("shouldn't be launching a parent process");
1637 case GeckoProcessType_IPDLUnitTest:
1638 // No handle duplication necessary.
1639 break;
1640 default:
1641 if (!SandboxBroker::AddTargetPeer(mResults.mHandle)) {
1642 NS_WARNING("Failed to add child process as target peer.");
1644 break;
1647 # endif // MOZ_SANDBOX
1649 return Ok();
1651 #endif // XP_WIN
1653 RefPtr<ProcessLaunchPromise> BaseProcessLauncher::FinishLaunch() {
1654 Result<Ok, LaunchError> aError = DoFinishLaunch();
1655 if (aError.isErr()) {
1656 return ProcessLaunchPromise::CreateAndReject(aError.unwrapErr(), __func__);
1659 MOZ_DIAGNOSTIC_ASSERT(mResults.mHandle);
1661 Telemetry::AccumulateTimeDelta(Telemetry::CHILD_PROCESS_LAUNCH_MS,
1662 mStartTimeStamp);
1664 return ProcessLaunchPromise::CreateAndResolve(mResults, __func__);
1667 bool GeckoChildProcessHost::OpenPrivilegedHandle(base::ProcessId aPid) {
1668 if (mChildProcessHandle) {
1669 MOZ_ASSERT(aPid == base::GetProcId(mChildProcessHandle));
1670 return true;
1673 return base::OpenPrivilegedProcessHandle(aPid, &mChildProcessHandle);
1676 void GeckoChildProcessHost::OnChannelConnected(base::ProcessId peer_pid) {
1678 mozilla::AutoWriteLock hLock(mHandleLock);
1679 if (!OpenPrivilegedHandle(peer_pid)) {
1680 MOZ_CRASH("can't open handle to child process");
1683 MonitorAutoLock lock(mMonitor);
1684 mProcessState = PROCESS_CONNECTED;
1685 lock.Notify();
1688 RefPtr<ProcessHandlePromise> GeckoChildProcessHost::WhenProcessHandleReady() {
1689 MOZ_ASSERT(mHandlePromise != nullptr);
1690 return mHandlePromise;
1693 #ifdef MOZ_WIDGET_ANDROID
1694 RefPtr<ProcessHandlePromise> AndroidProcessLauncher::LaunchAndroidService(
1695 const GeckoProcessType aType, const std::vector<std::string>& argv,
1696 const base::file_handle_mapping_vector& fds_to_remap) {
1697 MOZ_RELEASE_ASSERT((2 <= fds_to_remap.size()) && (fds_to_remap.size() <= 5));
1698 JNIEnv* const env = mozilla::jni::GetEnvForThread();
1699 MOZ_ASSERT(env);
1701 const int argvSize = argv.size();
1702 jni::ObjectArray::LocalRef jargs =
1703 jni::ObjectArray::New<jni::String>(argvSize);
1704 for (int ix = 0; ix < argvSize; ix++) {
1705 jargs->SetElement(ix, jni::StringParam(argv[ix].c_str(), env));
1708 // XXX: this processing depends entirely on the internals of
1709 // ContentParent::LaunchSubprocess()
1710 // GeckoChildProcessHost::PerformAsyncLaunch(), and the order in
1711 // which they append to fds_to_remap. There must be a better way to do it.
1712 // See bug 1440207.
1713 int32_t prefsFd = fds_to_remap[0].first;
1714 int32_t prefMapFd = fds_to_remap[1].first;
1715 int32_t ipcFd = fds_to_remap[2].first;
1716 int32_t crashFd = -1;
1717 if (fds_to_remap.size() == 4) {
1718 crashFd = fds_to_remap[3].first;
1721 auto type = java::GeckoProcessType::FromInt(aType);
1722 auto genericResult = java::GeckoProcessManager::Start(
1723 type, jargs, prefsFd, prefMapFd, ipcFd, crashFd);
1724 auto typedResult = java::GeckoResult::LocalRef(std::move(genericResult));
1725 return ProcessHandlePromise::FromGeckoResult(typedResult);
1727 #endif
1729 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
1730 bool GeckoChildProcessHost::AppendMacSandboxParams(StringVector& aArgs) {
1731 MacSandboxInfo info;
1732 if (NS_WARN_IF(!FillMacSandboxInfo(info))) {
1733 return false;
1735 info.AppendAsParams(aArgs);
1736 return true;
1739 // Fill |aInfo| with the flags needed to launch the utility sandbox
1740 bool GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
1741 aInfo.type = GetDefaultMacSandboxType();
1742 aInfo.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
1743 PR_GetEnv("MOZ_SANDBOX_LOGGING");
1745 nsAutoCString appPath;
1746 if (!nsMacUtilsImpl::GetAppPath(appPath)) {
1747 MOZ_CRASH("Failed to get app path");
1749 aInfo.appPath.assign(appPath.get());
1750 return true;
1753 void GeckoChildProcessHost::DisableOSActivityMode() {
1754 mDisableOSActivityMode = true;
1758 // If early sandbox startup is enabled for this process type, map the
1759 // process type to the sandbox type and enable the sandbox. Returns true
1760 // if no errors were encountered or if early sandbox startup is not
1761 // enabled for this process. Returns false if an error was encountered.
1763 /* static */
1764 bool GeckoChildProcessHost::StartMacSandbox(int aArgc, char** aArgv,
1765 std::string& aErrorMessage) {
1766 MacSandboxType sandboxType = MacSandboxType_Invalid;
1767 switch (XRE_GetProcessType()) {
1768 // For now, only support early sandbox startup for content,
1769 // RDD, and GMP processes. Add case statements for the additional
1770 // process types once early sandbox startup is implemented for them.
1771 case GeckoProcessType_Content:
1772 // Content processes don't use GeckoChildProcessHost
1773 // to configure sandboxing so hard code the sandbox type.
1774 sandboxType = MacSandboxType_Content;
1775 break;
1776 case GeckoProcessType_RDD:
1777 sandboxType = RDDProcessHost::GetMacSandboxType();
1778 break;
1779 case GeckoProcessType_Socket:
1780 sandboxType = net::SocketProcessHost::GetMacSandboxType();
1781 break;
1782 case GeckoProcessType_GMPlugin:
1783 sandboxType = gmp::GMPProcessParent::GetMacSandboxType();
1784 break;
1785 case GeckoProcessType_Utility:
1786 sandboxType = ipc::UtilityProcessHost::GetMacSandboxType();
1787 break;
1788 default:
1789 return true;
1792 return mozilla::StartMacSandboxIfEnabled(sandboxType, aArgc, aArgv,
1793 aErrorMessage);
1796 #endif /* XP_MACOSX && MOZ_SANDBOX */
1798 /* static */
1799 void GeckoChildProcessHost::GetAll(const GeckoProcessCallback& aCallback) {
1800 StaticMutexAutoLock lock(sMutex);
1801 if (!sGeckoChildProcessHosts) {
1802 return;
1804 for (GeckoChildProcessHost* gp = sGeckoChildProcessHosts->getFirst(); gp;
1805 gp = static_cast<mozilla::LinkedListElement<GeckoChildProcessHost>*>(gp)
1806 ->getNext()) {
1807 aCallback(gp);
1811 RefPtr<ProcessLaunchPromise> BaseProcessLauncher::Launch(
1812 GeckoChildProcessHost* aHost) {
1813 AssertIOThread();
1815 // The ForkServer doesn't use IPC::Channel for communication, so we can skip
1816 // initializing it.
1817 if (mProcessType != GeckoProcessType_ForkServer) {
1818 IPC::Channel::ChannelHandle serverHandle;
1819 if (!IPC::Channel::CreateRawPipe(&serverHandle, &mClientChannelHandle)) {
1820 return ProcessLaunchPromise::CreateAndReject(LaunchError("CreateRawPipe"),
1821 __func__);
1823 aHost->InitializeChannel(std::move(serverHandle));
1826 return InvokeAsync(mLaunchThread, this, __func__,
1827 &BaseProcessLauncher::PerformAsyncLaunch);
1830 } // namespace ipc
1831 } // namespace mozilla