From de686d23c18016f709853a0297c89dbfa0e847ce Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Wed, 13 Mar 2019 09:24:52 +0000 Subject: [PATCH] Bug 1530245 - Launch sandbox from new remote sandbox broker process. r=jld,bobowen Depends on D22051 Differential Revision: https://phabricator.services.mozilla.com/D22052 --HG-- extra : moz-landing-system : lando --- ipc/contentproc/plugin-container.cpp | 7 + ipc/glue/CrashReporterHost.cpp | 5 +- ipc/glue/GeckoChildProcessHost.cpp | 41 +++-- ipc/ipdl/sync-messages.ini | 2 + security/sandbox/moz.build | 1 + .../PRemoteSandboxBroker.ipdl | 35 ++++ .../RemoteSandboxBrokerChild.cpp | 86 ++++++++++ .../RemoteSandboxBrokerChild.h | 34 ++++ .../RemoteSandboxBrokerParent.cpp | 91 ++++++++++ .../RemoteSandboxBrokerParent.h | 43 +++++ .../RemoteSandboxBrokerProcessChild.cpp | 32 ++++ .../RemoteSandboxBrokerProcessChild.h | 33 ++++ .../RemoteSandboxBrokerProcessParent.cpp | 33 ++++ .../RemoteSandboxBrokerProcessParent.h | 46 +++++ .../win/src/remotesandboxbroker/moz.build | 35 ++++ .../remoteSandboxBroker.cpp | 159 ++++++++++++++++++ .../remotesandboxbroker/remoteSandboxBroker.h | 66 ++++++++ .../win/src/sandboxbroker/sandboxBroker.cpp | 86 +++++++--- .../win/src/sandboxbroker/sandboxBroker.h | 13 +- .../components/crashes/nsICrashService.idl | 3 +- toolkit/xre/nsAppRunner.cpp | 9 +- toolkit/xre/nsEmbedFunctions.cpp | 30 +++- xpcom/build/GeckoProcessTypes.h | 1 + xpcom/build/XREChildData.h | 6 + xpcom/components/nsComponentManager.cpp | 1 + xpcom/system/nsIXULRuntime.idl | 1 + 26 files changed, 844 insertions(+), 55 deletions(-) create mode 100644 security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.h create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.cpp create mode 100644 security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.h create mode 100644 security/sandbox/win/src/remotesandboxbroker/moz.build create mode 100644 security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp create mode 100644 security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.h diff --git a/ipc/contentproc/plugin-container.cpp b/ipc/contentproc/plugin-container.cpp index 5e836c20359e..290da8b9d900 100644 --- a/ipc/contentproc/plugin-container.cpp +++ b/ipc/contentproc/plugin-container.cpp @@ -46,6 +46,13 @@ int content_process_main(mozilla::Bootstrap* bootstrap, int argc, bootstrap->XRE_SetProcessType(argv[--argc]); +#if defined(XP_WIN) && defined(MOZ_SANDBOX) + if (bootstrap->XRE_GetProcessType() == GeckoProcessType_RemoteSandboxBroker) { + childData.sandboxBrokerServices = + mozilla::sandboxing::GetInitializedBrokerServices(); + } +#endif + nsresult rv = bootstrap->XRE_InitChildProcess(argc, argv, &childData); return NS_FAILED(rv); } diff --git a/ipc/glue/CrashReporterHost.cpp b/ipc/glue/CrashReporterHost.cpp index be01ce6fb12e..73fc5e567e27 100644 --- a/ipc/glue/CrashReporterHost.cpp +++ b/ipc/glue/CrashReporterHost.cpp @@ -44,9 +44,12 @@ static_assert(nsICrashService::PROCESS_TYPE_RDD == (int)GeckoProcessType_RDD, static_assert(nsICrashService::PROCESS_TYPE_SOCKET == (int)GeckoProcessType_Socket, "GeckoProcessType enum is out of sync with nsICrashService!"); +static_assert(nsICrashService::PROCESS_TYPE_SANDBOX_BROKER == + (int)GeckoProcessType_RemoteSandboxBroker, + "GeckoProcessType enum is out of sync with nsICrashService!"); // Add new static asserts here if you add more process types. // Update this static assert as well. -static_assert(nsICrashService::PROCESS_TYPE_SOCKET + 1 == +static_assert(nsICrashService::PROCESS_TYPE_SANDBOX_BROKER + 1 == (int)GeckoProcessType_End, "GeckoProcessType enum is out of sync with nsICrashService!"); diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp index 6f988fedada4..742d05b186ba 100644 --- a/ipc/glue/GeckoChildProcessHost.cpp +++ b/ipc/glue/GeckoChildProcessHost.cpp @@ -56,6 +56,9 @@ # include "mozilla/Preferences.h" # include "mozilla/sandboxing/sandboxLogging.h" # include "WinUtils.h" +# if defined(_ARM64_) +# include "mozilla/remoteSandboxBroker.h" +# endif # endif #endif @@ -103,7 +106,6 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType, mGroupId(u"-"), #endif #if defined(MOZ_SANDBOX) && defined(XP_WIN) - mSandboxBroker(new SandboxBroker()), mEnableSandboxLogging(false), mSandboxLevel(0), #endif @@ -151,6 +153,12 @@ GeckoChildProcessHost::~GeckoChildProcessHost() mChildProcessHandle); #endif } +#if defined(MOZ_SANDBOX) && defined(XP_WIN) + if (mSandboxBroker) { + mSandboxBroker->Shutdown(); + mSandboxBroker = nullptr; + } +#endif } void GeckoChildProcessHost::Destroy() { @@ -1020,19 +1028,22 @@ bool GeckoChildProcessHost::PerformAsyncLaunch( FilePath exePath; BinaryPathType pathType = GetPathToBinary(exePath, mProcessType); -# if defined(MOZ_SANDBOX) || (defined(_ARM64_) && defined(XP_WIN)) +# if defined(MOZ_SANDBOX) || defined(_ARM64_) const bool isGMP = mProcessType == GeckoProcessType_GMPlugin; const bool isWidevine = isGMP && Contains(aExtraOpts, "gmp-widevinecdm"); -# if defined(_ARM64_) && defined(XP_WIN) +# if defined(_ARM64_) const bool isClearKey = isGMP && Contains(aExtraOpts, "gmp-clearkey"); - if (isGMP && (isClearKey || isWidevine)) { - // On Windows on ARM64 for ClearKey and Widevine, 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. + 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. exePath = exePath.DirName().AppendASCII("i686").Append(exePath.BaseName()); } -# endif -# endif // defined(MOZ_SANDBOX) || (defined(_ARM64_) && defined(XP_WIN)) +# endif // if defined(_ARM64_) +# endif // defined(MOZ_SANDBOX) || defined(_ARM64_) CommandLine cmdLine(exePath.ToWStringHack()); @@ -1064,6 +1075,13 @@ bool GeckoChildProcessHost::PerformAsyncLaunch( } # if defined(MOZ_SANDBOX) +# if defined(_ARM64_) + if (isClearKey || isWidevine) + mSandboxBroker = new RemoteSandboxBroker(); + else +# endif // if defined(_ARM64_) + mSandboxBroker = new SandboxBroker(); + bool shouldSandboxCurrentProcess = false; // XXX: Bug 1124167: We should get rid of the process specific logic for @@ -1136,6 +1154,9 @@ bool GeckoChildProcessHost::PerformAsyncLaunch( case GeckoProcessType_Socket: // TODO - setup sandboxing for the socket process. break; + case GeckoProcessType_RemoteSandboxBroker: + // We don't sandbox the sandbox launcher... + break; case GeckoProcessType_Default: default: MOZ_CRASH("Bad process type in GeckoChildProcessHost"); @@ -1208,7 +1229,7 @@ bool GeckoChildProcessHost::PerformAsyncLaunch( // No handle duplication necessary. break; default: - if (!mSandboxBroker->AddTargetPeer(process)) { + if (!SandboxBroker::AddTargetPeer(process)) { NS_WARNING("Failed to add child process as target peer."); } break; diff --git a/ipc/ipdl/sync-messages.ini b/ipc/ipdl/sync-messages.ini index bdc2a0bc2208..fad32c2470ca 100644 --- a/ipc/ipdl/sync-messages.ini +++ b/ipc/ipdl/sync-messages.ini @@ -1059,3 +1059,5 @@ description = description = bug 1363126 [PClientSource::WorkerSyncPing] description = Synchronous ping allowing worker thread to confirm actor is created. Necessary to avoid racing with ClientHandle actors on main thread. +[PRemoteSandboxBroker::LaunchApp] +description = Synchronous launch of a child process that in turn launches and sandboxes another process. Called on a dedicated thread and targets a dedicated process, so this shouldn't block anything. diff --git a/security/sandbox/moz.build b/security/sandbox/moz.build index efda844b194a..f80e0bb35c52 100755 --- a/security/sandbox/moz.build +++ b/security/sandbox/moz.build @@ -20,6 +20,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT': FORCE_STATIC_LIB = True DIRS += [ + 'win/src/remotesandboxbroker', 'win/src/sandboxbroker', 'win/src/sandboxpermissions', 'win/src/sandboxtarget', diff --git a/security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl b/security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl new file mode 100644 index 000000000000..6aa11254c45f --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +using mozilla::dom::NativeThreadId from "mozilla/dom/TabMessageUtils.h"; + +namespace mozilla { + +struct EnvVar { + nsString name; + nsString value; +}; + +struct LaunchParameters { + nsString path; + nsString args; + EnvVar[] env; + uint32_t processType; + uint32_t sandboxLevel; + nsString[] allowedReadFiles; + uint64_t[] shareHandles; + bool enableLogging; +}; + +intr protocol PRemoteSandboxBroker +{ +parent: + async InitCrashReporter(Shmem shmem, NativeThreadId threadId); +child: + intr LaunchApp(LaunchParameters params) + returns (bool ok, uint64_t handle); +}; + +} // namespace mozilla diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp new file mode 100644 index 000000000000..230a05f5c8ec --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#include "RemoteSandboxBrokerChild.h" +#include "mozilla/ipc/CrashReporterClient.h" +#include "nsDebugImpl.h" +#include "mozilla/ipc/CrashReporterClient.h" +#include "RemoteSandboxBrokerProcessChild.h" + +using namespace mozilla::ipc; + +namespace mozilla { + +RemoteSandboxBrokerChild::RemoteSandboxBrokerChild() { + nsDebugImpl::SetMultiprocessMode("RemoteSandboxBroker"); +} + +RemoteSandboxBrokerChild::~RemoteSandboxBrokerChild() {} + +bool RemoteSandboxBrokerChild::Init(base::ProcessId aParentPid, + MessageLoop* aIOLoop, + IPC::Channel* aChannel) { + if (NS_WARN_IF(!Open(aChannel, aParentPid, aIOLoop))) { + return false; + } + CrashReporterClient::InitSingleton(this); + return true; +} + +void RemoteSandboxBrokerChild::ActorDestroy(ActorDestroyReason aWhy) { + if (AbnormalShutdown == aWhy) { + NS_WARNING("Abnormal shutdown of GMP process!"); + ipc::ProcessChild::QuickExit(); + } + CrashReporterClient::DestroySingleton(); + XRE_ShutdownChildProcess(); +} + +mozilla::ipc::IPCResult RemoteSandboxBrokerChild::AnswerLaunchApp( + LaunchParameters&& aParams, bool* aOutOk, uint64_t* aOutHandle) { + auto towstring = [](const nsString& s) { + return std::wstring(s.get(), s.Length()); + }; + + base::EnvironmentMap envmap; + for (const EnvVar& env : aParams.env()) { + envmap[towstring(env.name())] = towstring(env.value()); + } + + if (!mSandboxBroker.SetSecurityLevelForGMPlugin( + AbstractSandboxBroker::SandboxLevel(aParams.sandboxLevel()))) { + *aOutOk = false; + return IPC_OK(); + } + + for (const auto& path : aParams.allowedReadFiles()) { + if (!mSandboxBroker.AllowReadFile(path.get())) { + *aOutOk = false; + return IPC_OK(); + } + } + + for (const auto& handle : aParams.shareHandles()) { + mSandboxBroker.AddHandleToShare(HANDLE(handle)); + } + + HANDLE p; + *aOutOk = + mSandboxBroker.LaunchApp(aParams.path().get(), aParams.args().get(), + envmap, GeckoProcessType(aParams.processType()), + aParams.enableLogging(), (void**)&p); + if (*aOutOk) { + *aOutHandle = uint64_t(p); + } + + for (const auto& handle : aParams.shareHandles()) { + CloseHandle(HANDLE(handle)); + } + + return IPC_OK(); +} + +} // namespace mozilla diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h new file mode 100644 index 000000000000..9481b5438228 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h @@ -0,0 +1,34 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#ifndef RemoteSandboxBrokerChild_h_ +#define RemoteSandboxBrokerChild_h_ + +#include "mozilla/PRemoteSandboxBrokerChild.h" +#include "sandboxBroker.h" + +namespace mozilla { + +class RemoteSandboxBrokerChild : public PRemoteSandboxBrokerChild { + friend class PRemoteSandboxBrokerChild; + + public: + RemoteSandboxBrokerChild(); + virtual ~RemoteSandboxBrokerChild(); + bool Init(base::ProcessId aParentPid, MessageLoop* aIOLoop, + IPC::Channel* aChannel); + + private: + mozilla::ipc::IPCResult AnswerLaunchApp(LaunchParameters&& aParams, + bool* aOutOk, uint64_t* aOutHandle); + + void ActorDestroy(ActorDestroyReason aWhy); + SandboxBroker mSandboxBroker; +}; + +} // namespace mozilla + +#endif diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp new file mode 100644 index 000000000000..bf6fbca3c5dd --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#include "RemoteSandboxBrokerParent.h" +#include "RemoteSandboxBrokerProcessParent.h" +#include "mozilla/Telemetry.h" +#include + +namespace mozilla { + +RefPtr RemoteSandboxBrokerParent::Launch( + const nsTArray& aHandlesToShare) { + MOZ_ASSERT(!mProcess); + if (mProcess) { + // Don't re-init. + return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } + + mProcess = new RemoteSandboxBrokerProcessParent(); + for (uint64_t handle : aHandlesToShare) { + mProcess->AddHandleToShare(HANDLE(handle)); + } + + // Note: we rely on the caller to keep this instance alive while we launch + // the process, so that these closures point to valid memory. + auto resolve = [this](base::ProcessHandle handle) { + mOpened = Open(mProcess->GetChannel(), base::GetProcId(handle)); + if (!mOpened) { + mProcess->Destroy(); + mProcess = nullptr; + return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + } + return GenericPromise::CreateAndResolve(true, __func__); + }; + + auto reject = [this]() { + NS_ERROR("failed to launch child in the parent"); + if (mProcess) { + mProcess->Destroy(); + mProcess = nullptr; + } + return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + }; + + return mProcess->AsyncLaunch()->Then(GetCurrentThreadSerialEventTarget(), + __func__, std::move(resolve), + std::move(reject)); +} + +bool RemoteSandboxBrokerParent::DuplicateFromLauncher(HANDLE aLauncherHandle, + LPHANDLE aOurHandle) { + return ::DuplicateHandle(mProcess->GetChildProcessHandle(), aLauncherHandle, + ::GetCurrentProcess(), aOurHandle, 0, false, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE); +} + +void RemoteSandboxBrokerParent::ActorDestroy(ActorDestroyReason aWhy) { + if (AbnormalShutdown == aWhy) { + Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT, + NS_LITERAL_CSTRING("sandboxbroker"), 1); + if (mCrashReporter) { + mCrashReporter->GenerateCrashReport(OtherPid()); + mCrashReporter = nullptr; + } + } + Shutdown(); +} + +void RemoteSandboxBrokerParent::Shutdown() { + if (mOpened) { + mOpened = false; + Close(); + } + if (mProcess) { + mProcess->Destroy(); + mProcess = nullptr; + } +} + +mozilla::ipc::IPCResult RemoteSandboxBrokerParent::RecvInitCrashReporter( + Shmem&& aShmem, const NativeThreadId& aThreadId) { + mCrashReporter = MakeUnique( + GeckoProcessType_RemoteSandboxBroker, aShmem, aThreadId); + + return IPC_OK(); +} + +} // namespace mozilla diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h new file mode 100644 index 000000000000..0ced9d2497b1 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#ifndef RemoteSandboxBrokerParent_h_ +#define RemoteSandboxBrokerParent_h_ + +#include "mozilla/PRemoteSandboxBrokerParent.h" +#include "RemoteSandboxBrokerProcessParent.h" +#include "mozilla/ipc/CrashReporterHost.h" + +namespace mozilla { + +class RemoteSandboxBrokerParent : public PRemoteSandboxBrokerParent { + friend class PRemoteSandboxBrokerParent; + + public: + bool DuplicateFromLauncher(HANDLE aLauncherHandle, LPHANDLE aOurHandle); + + void Shutdown(); + + // Asynchronously launches the launcher process. + // Note: we rely on the caller to keep this instance alive + // until this promise resolves. + RefPtr Launch(const nsTArray& aHandlesToShare); + + private: + mozilla::ipc::IPCResult RecvInitCrashReporter( + Shmem&& aShmem, const NativeThreadId& aThreadId); + + void ActorDestroy(ActorDestroyReason aWhy) override; + + RemoteSandboxBrokerProcessParent* mProcess = nullptr; + + bool mOpened = false; + UniquePtr mCrashReporter; +}; + +} // namespace mozilla + +#endif // RemoteSandboxBrokerParent_h_ diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp new file mode 100644 index 000000000000..460628181e12 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp @@ -0,0 +1,32 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#include "RemoteSandboxBrokerProcessChild.h" + +#include "mozilla/ipc/IOThreadChild.h" +#include "mozilla/BackgroundHangMonitor.h" + +using mozilla::ipc::IOThreadChild; + +namespace mozilla { + +RemoteSandboxBrokerProcessChild::RemoteSandboxBrokerProcessChild( + ProcessId aParentPid) + : ProcessChild(aParentPid) {} + +RemoteSandboxBrokerProcessChild::~RemoteSandboxBrokerProcessChild() {} + +bool RemoteSandboxBrokerProcessChild::Init(int aArgc, char* aArgv[]) { + BackgroundHangMonitor::Startup(); + return mSandboxBrokerChild.Init(ParentPid(), IOThreadChild::message_loop(), + IOThreadChild::channel()); +} + +void RemoteSandboxBrokerProcessChild::CleanUp() { + BackgroundHangMonitor::Shutdown(); +} + +} // namespace mozilla diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.h b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.h new file mode 100644 index 000000000000..83121a9bb504 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.h @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#ifndef RemoteSandboxBrokerProcessChild_h_ +#define RemoteSandboxBrokerProcessChild_h_ + +#include "mozilla/ipc/ProcessChild.h" +#include "RemoteSandboxBrokerChild.h" + +namespace mozilla { + +class RemoteSandboxBrokerProcessChild final + : public mozilla::ipc::ProcessChild { + protected: + typedef mozilla::ipc::ProcessChild ProcessChild; + + public: + explicit RemoteSandboxBrokerProcessChild(ProcessId aParentPid); + ~RemoteSandboxBrokerProcessChild(); + + bool Init(int aArgc, char* aArgv[]) override; + void CleanUp() override; + + private: + RemoteSandboxBrokerChild mSandboxBrokerChild; + DISALLOW_COPY_AND_ASSIGN(RemoteSandboxBrokerProcessChild); +}; + +} // namespace mozilla + +#endif // GMPProcessChild_h_ diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.cpp b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.cpp new file mode 100644 index 000000000000..9442e9301e23 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.cpp @@ -0,0 +1,33 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#include "RemoteSandboxBrokerProcessParent.h" +#include "nsIRunnable.h" +#include + +using mozilla::ipc::GeckoChildProcessHost; + +namespace mozilla { + +RemoteSandboxBrokerProcessParent::RemoteSandboxBrokerProcessParent() + : GeckoChildProcessHost(GeckoProcessType_RemoteSandboxBroker) { + MOZ_COUNT_CTOR(RemoteSandboxBrokerProcessParent); +} + +RemoteSandboxBrokerProcessParent::~RemoteSandboxBrokerProcessParent() { + MOZ_COUNT_DTOR(RemoteSandboxBrokerProcessParent); +} + +RefPtr +RemoteSandboxBrokerProcessParent::AsyncLaunch() { + if (!GeckoChildProcessHost::AsyncLaunch()) { + return HandlePromise::CreateAndReject(GeckoChildProcessHost::LaunchError{}, + __func__); + } + return WhenProcessHandleReady(); +} + +} // namespace mozilla diff --git a/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.h b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.h new file mode 100644 index 000000000000..cdba9ec2ed9a --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.h @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=4 et : + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef RemoteSandboxBrokerProcessParent_h_ +#define RemoteSandboxBrokerProcessParent_h_ + +#include "mozilla/Attributes.h" +#include "base/basictypes.h" +#include "base/file_path.h" +#include "base/thread.h" +#include "chrome/common/child_process_host.h" +#include "mozilla/ipc/GeckoChildProcessHost.h" + +class nsIRunnable; + +namespace mozilla { + +class RemoteSandboxBrokerProcessParent final + : public mozilla::ipc::GeckoChildProcessHost { + public: + using LaunchError = GeckoChildProcessHost::LaunchError; + using LaunchPromise = GeckoChildProcessHost::LaunchPromise; + + RemoteSandboxBrokerProcessParent(); + + using GeckoChildProcessHost::HandlePromise; + + RefPtr AsyncLaunch(); + + bool CanShutdown() override { return true; } + + using mozilla::ipc::GeckoChildProcessHost::GetChannel; + using mozilla::ipc::GeckoChildProcessHost::GetChildProcessHandle; + + private: + ~RemoteSandboxBrokerProcessParent(); + + DISALLOW_COPY_AND_ASSIGN(RemoteSandboxBrokerProcessParent); +}; + +} // namespace mozilla + +#endif // ifndef GMPProcessParent_h diff --git a/security/sandbox/win/src/remotesandboxbroker/moz.build b/security/sandbox/win/src/remotesandboxbroker/moz.build new file mode 100644 index 000000000000..3fbda1062d6a --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/moz.build @@ -0,0 +1,35 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +SOURCES += [ + 'remoteSandboxBroker.cpp', + 'RemoteSandboxBrokerChild.cpp', + 'RemoteSandboxBrokerParent.cpp', + 'RemoteSandboxBrokerProcessChild.cpp', + 'RemoteSandboxBrokerProcessParent.cpp', +] + +EXPORTS.mozilla += [ + 'remoteSandboxBroker.h', + 'RemoteSandboxBrokerChild.h', + 'RemoteSandboxBrokerParent.h', + 'RemoteSandboxBrokerProcessChild.h', + 'RemoteSandboxBrokerProcessParent.h', +] + +for var in ('UNICODE', '_UNICODE'): + DEFINES[var] = True + +FINAL_LIBRARY = 'xul' + +if CONFIG['CC_TYPE'] == 'clang-cl': + AllowCompilerWarnings() # workaround for bug 1090497 + +IPDL_SOURCES += [ + 'PRemoteSandboxBroker.ipdl' +] + +include('/ipc/chromium/chromium-config.mozbuild') diff --git a/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp new file mode 100644 index 000000000000..cb96b66b886a --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#include "remoteSandboxBroker.h" + +namespace mozilla { + +RemoteSandboxBroker::RemoteSandboxBroker() {} + +RemoteSandboxBroker::~RemoteSandboxBroker() { + MOZ_ASSERT( + mShutdown, + "Shutdown must be called on RemoteSandboxBroker before destruction!"); +} + +void RemoteSandboxBroker::Shutdown() { + MOZ_ASSERT(!mShutdown, "Don't call Shutdown() twice!"); + mShutdown = true; + + if (!mIPCLaunchThread) { + // Can't have launched child process, nothing to shutdown. + return; + } + + RefPtr self = this; + mIPCLaunchThread->Dispatch( + NS_NewRunnableFunction("Remote Sandbox Launch", [self, this]() { + // Note: `self` here should be the last reference to this instance. + mParent.Shutdown(); + mIPCLaunchThread = nullptr; + })); +} + +bool RemoteSandboxBroker::LaunchApp(const wchar_t *aPath, + const wchar_t *aArguments, + base::EnvironmentMap &aEnvironment, + GeckoProcessType aProcessType, + const bool aEnableLogging, + void **aProcessHandle) { + // Note: we expect to be called on the IPC launch thread from + // GeckoChildProcesHost while it's launching a child process. We can't + // run a synchronous launch here as that blocks the calling thread while + // it dispatches a task to the IPC launch thread to spawn the process. + // Since our calling thread is the IPC launch thread, we'd then be + // deadlocked. So instead we do an async launch, and spin the event + // loop until the process launch succeeds. + + // We should be on the IPC launch thread. We're shutdown on the IO thread, + // so save a ref to the IPC launch thread here, so we can close the channel + // on the IPC launch thread on shutdown. + mIPCLaunchThread = GetCurrentThreadEventTarget(); + + mParameters.path() = nsDependentString(aPath); + mParameters.args() = nsDependentString(aArguments); + + auto toNsString = [](const std::wstring &s) { + return nsDependentString(s.c_str()); + }; + for (auto itr : aEnvironment) { + mParameters.env().AppendElement( + EnvVar(toNsString(itr.first), toNsString(itr.second))); + } + + mParameters.processType() = uint32_t(aProcessType); + mParameters.enableLogging() = aEnableLogging; + + enum Result { Pending, Succeeded, Failed }; + Result res = Pending; + auto resolve = [&](bool ok) { + res = Succeeded; + return GenericPromise::CreateAndResolve(ok, __func__); + }; + + auto reject = [&](nsresult) { + res = Failed; + return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__); + }; + + mParent.Launch(mParameters.shareHandles()) + ->Then(GetCurrentThreadSerialEventTarget(), __func__, std::move(resolve), + std::move(reject)); + + // Spin the event loop while the sandbox launcher process launches. + SpinEventLoopUntil([&]() { return res != Pending; }); + + if (res == Failed) { + return false; + } + + uint64_t handle = 0; + bool ok = false; + bool rv = mParent.CallLaunchApp(std::move(mParameters), &ok, &handle) && ok; + mParameters.shareHandles().Clear(); + if (!rv) { + return false; + } + + // Duplicate the handle of the child process that the launcher launched from + // the launcher process's space into this process' space. + HANDLE ourChildHandle = 0; + bool dh = mParent.DuplicateFromLauncher((HANDLE)handle, &ourChildHandle); + if (!dh) { + return false; + } + + *aProcessHandle = (void **)(ourChildHandle); + + base::ProcessHandle process = *aProcessHandle; + SandboxBroker::AddTargetPeer(process); + + return true; +} + +bool RemoteSandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel) { + mParameters.sandboxLevel() = uint32_t(aLevel); + return true; +} + +bool RemoteSandboxBroker::AllowReadFile(wchar_t const *aFile) { + mParameters.allowedReadFiles().AppendElement(nsDependentString(aFile)); + return true; +} + +void RemoteSandboxBroker::AddHandleToShare(HANDLE aHandle) { + mParameters.shareHandles().AppendElement(uint64_t(aHandle)); +} + +#ifdef MOZ_CONTENT_SANDBOX +void RemoteSandboxBroker::SetSecurityLevelForContentProcess( + int32_t aSandboxLevel, bool aIsFileProcess) { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForContentProcess not Implemented"); +} +#endif + +void RemoteSandboxBroker::SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForGPUProcess not Implemented"); +} + +bool RemoteSandboxBroker::SetSecurityLevelForRDDProcess() { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForRDDProcess not Implemented"); +} + +bool RemoteSandboxBroker::SetSecurityLevelForPluginProcess( + int32_t aSandboxLevel) { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForPluginProcess not Implemented"); +} + +AbstractSandboxBroker *CreateRemoteSandboxBroker() { + return new RemoteSandboxBroker(); +} + +} // namespace mozilla diff --git a/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.h b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.h new file mode 100644 index 000000000000..bc8e77e8ee4e --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 https://mozilla.org/MPL/2.0/. */ + +#ifndef __REMOTE_SANDBOXBROKER_H__ +#define __REMOTE_SANDBOXBROKER_H__ + +#include "sandboxBroker.h" +#include "RemoteSandboxBrokerParent.h" + +namespace mozilla { + +// To make sandboxing an x86 plugin-container process on Windows on ARM64, +// we launch an x86 child process which in turn launches and sandboxes the x86 +// plugin-container child. This means the sandbox broker (in the remote +// x86 sandbox launcher process) can be same-arch with the process that it's +// sandboxing, which means all the sandbox's assumptions about things being +// same arch still hold. +class RemoteSandboxBroker : public AbstractSandboxBroker { + public: + RemoteSandboxBroker(); + + void Shutdown() override; + + // Note: This should be called on the IPC launch thread, and this spins + // the event loop. So this means potentially another IPC launch could occur + // re-entrantly while calling this. + bool LaunchApp(const wchar_t *aPath, const wchar_t *aArguments, + base::EnvironmentMap &aEnvironment, + GeckoProcessType aProcessType, const bool aEnableLogging, + void **aProcessHandle) override; + + // Security levels for different types of processes +#if defined(MOZ_CONTENT_SANDBOX) + void SetSecurityLevelForContentProcess(int32_t aSandboxLevel, + bool aIsFileProcess) override; +#endif + void SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) override; + bool SetSecurityLevelForRDDProcess() override; + bool SetSecurityLevelForPluginProcess(int32_t aSandboxLevel) override; + bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel) override; + bool AllowReadFile(wchar_t const *file) override; + void AddHandleToShare(HANDLE aHandle) override; + + private: + virtual ~RemoteSandboxBroker(); + + // Parameters that we use to launch the child process. + LaunchParameters mParameters; + + RemoteSandboxBrokerParent mParent; + + // We bind the RemoteSandboxBrokerParent to the IPC launch thread. + // As such, we must close its channel on the same thread. So we save + // a reference to the IPC launch thread here. + nsCOMPtr mIPCLaunchThread; + + // True if we've been shutdown. + bool mShutdown = false; +}; + +} // namespace mozilla + +#endif // __REMOTE_SANDBOXBROKER_H__ diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp index 7e5bae8e817a..e304d0082694 100644 --- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.cpp @@ -97,43 +97,54 @@ static void CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey, void SandboxBroker::GeckoDependentInitialize() { MOZ_ASSERT(NS_IsMainThread()); - // Cache directory paths for use in policy rules, because the directory - // service must be called on the main thread. - nsresult rv; - nsCOMPtr dirSvc = - do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); - if (NS_FAILED(rv)) { - MOZ_ASSERT( - false, - "Failed to get directory service, cannot cache directories for rules."); - LOG_E( - "Failed to get directory service, cannot cache directories for rules."); - return; - } + bool haveXPCOM = XRE_GetProcessType() != GeckoProcessType_RemoteSandboxBroker; + if (haveXPCOM) { + // Cache directory paths for use in policy rules, because the directory + // service must be called on the main thread. + nsresult rv; + nsCOMPtr dirSvc = + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv); + if (NS_FAILED(rv)) { + MOZ_ASSERT(false, + "Failed to get directory service, cannot cache directories " + "for rules."); + LOG_E( + "Failed to get directory service, cannot cache directories for " + "rules."); + return; + } - CacheDirAndAutoClear(dirSvc, NS_GRE_DIR, &sBinDir); - CacheDirAndAutoClear(dirSvc, NS_APP_USER_PROFILE_50_DIR, &sProfileDir); - CacheDirAndAutoClear(dirSvc, NS_APP_CONTENT_PROCESS_TEMP_DIR, - &sContentTempDir); - CacheDirAndAutoClear(dirSvc, NS_APP_PLUGIN_PROCESS_TEMP_DIR, &sPluginTempDir); - CacheDirAndAutoClear(dirSvc, NS_WIN_APPDATA_DIR, &sRoamingAppDataDir); - CacheDirAndAutoClear(dirSvc, NS_WIN_LOCAL_APPDATA_DIR, &sLocalAppDataDir); - CacheDirAndAutoClear(dirSvc, XRE_USER_SYS_EXTENSION_DEV_DIR, - &sUserExtensionsDevDir); + CacheDirAndAutoClear(dirSvc, NS_GRE_DIR, &sBinDir); + CacheDirAndAutoClear(dirSvc, NS_APP_USER_PROFILE_50_DIR, &sProfileDir); + CacheDirAndAutoClear(dirSvc, NS_APP_CONTENT_PROCESS_TEMP_DIR, + &sContentTempDir); + CacheDirAndAutoClear(dirSvc, NS_APP_PLUGIN_PROCESS_TEMP_DIR, + &sPluginTempDir); + CacheDirAndAutoClear(dirSvc, NS_WIN_APPDATA_DIR, &sRoamingAppDataDir); + CacheDirAndAutoClear(dirSvc, NS_WIN_LOCAL_APPDATA_DIR, &sLocalAppDataDir); + CacheDirAndAutoClear(dirSvc, XRE_USER_SYS_EXTENSION_DEV_DIR, + &sUserExtensionsDevDir); #ifdef ENABLE_SYSTEM_EXTENSION_DIRS - CacheDirAndAutoClear(dirSvc, XRE_USER_SYS_EXTENSION_DIR, &sUserExtensionsDir); + CacheDirAndAutoClear(dirSvc, XRE_USER_SYS_EXTENSION_DIR, + &sUserExtensionsDir); #endif + } // Create sLaunchErrors up front because ClearOnShutdown must be called on the // main thread. sLaunchErrors = MakeUnique>(); ClearOnShutdown(&sLaunchErrors); - // Cache prefs that are needed off main thread. - Preferences::AddBoolVarCache(&sRddWin32kDisable, - "security.sandbox.rdd.win32k-disable"); - Preferences::AddBoolVarCache(&sGmpWin32kDisable, - "security.sandbox.gmp.win32k-disable"); + if (haveXPCOM) { + // Cache prefs that are needed off main thread. + Preferences::AddBoolVarCache(&sRddWin32kDisable, + "security.sandbox.rdd.win32k-disable"); + Preferences::AddBoolVarCache(&sGmpWin32kDisable, + "security.sandbox.gmp.win32k-disable"); + } else { + sRddWin32kDisable = false; + sGmpWin32kDisable = false; + } } SandboxBroker::SandboxBroker() { @@ -1164,6 +1175,7 @@ bool SandboxBroker::AllowReadFile(wchar_t const* file) { return true; } +/* static */ bool SandboxBroker::AddTargetPeer(HANDLE aPeerProcess) { if (!sBrokerService) { return false; @@ -1204,4 +1216,22 @@ SandboxBroker::~SandboxBroker() { } } +#ifdef _ARM64_ +// We can't include remoteSandboxBroker.h here directly, as it includes +// IPDL headers, which include a different copy of the chromium base +// libraries, which leads to conflicts. +extern AbstractSandboxBroker* CreateRemoteSandboxBroker(); +#endif + +// static +AbstractSandboxBroker* AbstractSandboxBroker::Create( + GeckoProcessType aProcessType) { +#ifdef _ARM64_ + if (aProcessType == GeckoProcessType_GMPlugin) { + return CreateRemoteSandboxBroker(); + } +#endif + return new SandboxBroker(); +} + } // namespace mozilla diff --git a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h index de27c9b31192..0a8c89e18f89 100644 --- a/security/sandbox/win/src/sandboxbroker/sandboxBroker.h +++ b/security/sandbox/win/src/sandboxbroker/sandboxBroker.h @@ -26,6 +26,9 @@ class AbstractSandboxBroker { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbstractSandboxBroker) + static AbstractSandboxBroker *Create(GeckoProcessType aProcessType); + + virtual void Shutdown() = 0; virtual bool LaunchApp(const wchar_t *aPath, const wchar_t *aArguments, base::EnvironmentMap &aEnvironment, GeckoProcessType aProcessType, @@ -47,12 +50,6 @@ class AbstractSandboxBroker { // File system permissions virtual bool AllowReadFile(wchar_t const *file) = 0; - /** - * Exposes AddTargetPeer from broker services, so that non-sandboxed - * processes can be added as handle duplication targets. - */ - virtual bool AddTargetPeer(HANDLE aPeerProcess) = 0; - /** * Share a HANDLE with the child process. The HANDLE will be made available * in the child process at the memory address @@ -71,6 +68,8 @@ class SandboxBroker : public AbstractSandboxBroker { static void Initialize(sandbox::BrokerServices *aBrokerServices); + void Shutdown() override {} + /** * Do initialization that depends on parts of the Gecko machinery having been * created first. @@ -102,7 +101,7 @@ class SandboxBroker : public AbstractSandboxBroker { * Exposes AddTargetPeer from broker services, so that non-sandboxed * processes can be added as handle duplication targets. */ - bool AddTargetPeer(HANDLE aPeerProcess) override; + static bool AddTargetPeer(HANDLE aPeerProcess); /** * Share a HANDLE with the child process. The HANDLE will be made available diff --git a/toolkit/components/crashes/nsICrashService.idl b/toolkit/components/crashes/nsICrashService.idl index 78a3465c89ed..159c41fe4a4f 100644 --- a/toolkit/components/crashes/nsICrashService.idl +++ b/toolkit/components/crashes/nsICrashService.idl @@ -4,7 +4,7 @@ #include "nsISupports.idl" -[scriptable, uuid(f60d76e5-62c3-4f58-89f6-b726c2b7bc20)] +[scriptable, uuid(70bd93ff-88fa-4600-8af8-57c8d002dbac)] interface nsICrashService : nsISupports { /** @@ -30,6 +30,7 @@ interface nsICrashService : nsISupports const long PROCESS_TYPE_VR = 6; const long PROCESS_TYPE_RDD = 7; const long PROCESS_TYPE_SOCKET = 8; + const long PROCESS_TYPE_SANDBOX_BROKER = 9; // New process types should be added at the end of the above list. const long CRASH_TYPE_CRASH = 0; diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index 302e4083a01d..db2619cad50b 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -631,9 +631,10 @@ SYNC_ENUMS(GPU, GPU) SYNC_ENUMS(VR, VR) SYNC_ENUMS(RDD, RDD) SYNC_ENUMS(SOCKET, Socket) +SYNC_ENUMS(SANDBOX_BROKER, RemoteSandboxBroker) // .. and ensure that that is all of them: -static_assert(GeckoProcessType_Socket + 1 == GeckoProcessType_End, +static_assert(GeckoProcessType_RemoteSandboxBroker + 1 == GeckoProcessType_End, "Did not find the final GeckoProcessType"); NS_IMETHODIMP @@ -1535,11 +1536,11 @@ static const char kShieldPrefName[] = "app.shield.optoutstudies.enabled"; static void OnLauncherPrefChanged(const char* aPref, void* aData) { const bool kLauncherPrefDefaultValue = # if defined(NIGHTLY_BUILD) || (MOZ_UPDATE_CHANNEL == beta) - true + true # else - false + false # endif // defined(NIGHTLY_BUILD) || (MOZ_UPDATE_CHANNEL == beta) - ; + ; bool prefVal = Preferences::GetBool(kShieldPrefName, false) && Preferences::GetBool(PREF_WIN_LAUNCHER_PROCESS_ENABLED, kLauncherPrefDefaultValue); diff --git a/toolkit/xre/nsEmbedFunctions.cpp b/toolkit/xre/nsEmbedFunctions.cpp index a0d94c628dd6..2c4f45ba8567 100644 --- a/toolkit/xre/nsEmbedFunctions.cpp +++ b/toolkit/xre/nsEmbedFunctions.cpp @@ -91,6 +91,7 @@ #if defined(MOZ_SANDBOX) && defined(XP_WIN) # include "mozilla/sandboxTarget.h" # include "mozilla/sandboxing/loggingCallbacks.h" +# include "mozilla/RemoteSandboxBrokerProcessChild.h" #endif #if defined(MOZ_CONTENT_SANDBOX) @@ -123,6 +124,11 @@ using mozilla::_ipdltest::IPDLUnitTestProcessChild; # include "jprof.h" #endif +#if defined(XP_WIN) && defined(MOZ_SANDBOX) +# include "mozilla/sandboxing/SandboxInitialization.h" +# include "mozilla/sandboxing/sandboxLogging.h" +#endif + #include "VRProcessChild.h" using namespace mozilla; @@ -646,6 +652,7 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[], uiLoopType = MessageLoop::TYPE_MOZILLA_CHILD; break; case GeckoProcessType_GMPlugin: + case GeckoProcessType_RemoteSandboxBroker: uiLoopType = MessageLoop::TYPE_DEFAULT; break; default: @@ -653,6 +660,13 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[], break; } +#if defined(MOZ_SANDBOX) && defined(XP_WIN) + if (aChildData->sandboxBrokerServices) { + SandboxBroker::Initialize(aChildData->sandboxBrokerServices); + SandboxBroker::GeckoDependentInitialize(); + } +#endif + // If we are recording or replaying, initialize state and update arguments // according to those which were captured by the MiddlemanProcessChild in the // middleman process. No argument manipulation should happen between this @@ -715,6 +729,11 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[], process = new net::SocketProcessImpl(parentPID); break; +#if defined(MOZ_SANDBOX) && defined(XP_WIN) + case GeckoProcessType_RemoteSandboxBroker: + process = new RemoteSandboxBrokerProcessChild(parentPID); + break; +#endif default: MOZ_CRASH("Unknown main thread class"); } @@ -736,10 +755,13 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[], mozilla::sandboxing::InitLoggingIfRequired( aChildData->ProvideLogFunction); #endif - mozilla::FilePreferences::InitDirectoriesWhitelist(); - mozilla::FilePreferences::InitPrefs(); - - OverrideDefaultLocaleIfNeeded(); + if (XRE_GetProcessType() != GeckoProcessType_RemoteSandboxBroker) { + // Remote sandbox launcher process doesn't have prerequisites for + // these... + mozilla::FilePreferences::InitDirectoriesWhitelist(); + mozilla::FilePreferences::InitPrefs(); + OverrideDefaultLocaleIfNeeded(); + } #if defined(MOZ_CONTENT_SANDBOX) AddContentSandboxLevelAnnotation(); diff --git a/xpcom/build/GeckoProcessTypes.h b/xpcom/build/GeckoProcessTypes.h index c34af0fa98b3..ae9f372d027d 100644 --- a/xpcom/build/GeckoProcessTypes.h +++ b/xpcom/build/GeckoProcessTypes.h @@ -28,3 +28,4 @@ GECKO_PROCESS_TYPE(VR, "vr", VR) GECKO_PROCESS_TYPE(RDD, "rdd", RDD) // Socket process GECKO_PROCESS_TYPE(Socket, "socket", Socket) +GECKO_PROCESS_TYPE(RemoteSandboxBroker, "sandbox", RemoteSandboxBroker) diff --git a/xpcom/build/XREChildData.h b/xpcom/build/XREChildData.h index aa99f37d649e..6403b898833c 100644 --- a/xpcom/build/XREChildData.h +++ b/xpcom/build/XREChildData.h @@ -31,6 +31,12 @@ struct XREChildData { * Function to provide a logging function to the chromium sandbox code. */ mozilla::sandboxing::ProvideLogFunctionCb ProvideLogFunction = nullptr; + + /** + * Chromium sandbox broker services; needed by the remote sandbox + * launcher process. + */ + sandbox::BrokerServices* sandboxBrokerServices = nullptr; #endif }; diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp index 40547f21bffe..717b24322623 100644 --- a/xpcom/components/nsComponentManager.cpp +++ b/xpcom/components/nsComponentManager.cpp @@ -512,6 +512,7 @@ nsresult nsComponentManagerImpl::Init() { // We are going to assume that only a select few (see below) process types // want to load chrome manifests, and that any new process types will not // want to load them, because they're not going to be executing JS. + case GeckoProcessType_RemoteSandboxBroker: default: loadChromeManifests = false; break; diff --git a/xpcom/system/nsIXULRuntime.idl b/xpcom/system/nsIXULRuntime.idl index 636bee1517a3..83ceef691059 100644 --- a/xpcom/system/nsIXULRuntime.idl +++ b/xpcom/system/nsIXULRuntime.idl @@ -79,6 +79,7 @@ interface nsIXULRuntime : nsISupports const unsigned long PROCESS_TYPE_VR = 6; const unsigned long PROCESS_TYPE_RDD = 7; const unsigned long PROCESS_TYPE_SOCKET = 8; + const unsigned long PROCESS_TYPE_SANDBOX_BROKER = 9; /** * The type of the caller's process. Returns one of the values above.