diff options
Diffstat (limited to 'security/sandbox/win/src/remotesandboxbroker')
12 files changed, 695 insertions, 0 deletions
diff --git a/security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl b/security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl new file mode 100644 index 0000000000..876ed56c86 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl @@ -0,0 +1,36 @@ +/* -*- 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/NativeThreadId.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; +}; + +[ManualDealloc, NeedsOtherPid, NestedUpTo=inside_sync] +sync protocol PRemoteSandboxBroker +{ +parent: + async InitCrashReporter(NativeThreadId threadId); +child: + [Nested=inside_sync] sync 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 0000000000..2756ceb958 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp @@ -0,0 +1,96 @@ +/* -*- 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 "chrome/common/ipc_channel.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(mozilla::ipc::UntypedEndpoint&& aEndpoint) { + if (NS_WARN_IF(!aEndpoint.Bind(this))) { + 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::RecvLaunchApp( + 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()); + } + + // We need to add our parent as a target peer, so that the sandboxed child can + // duplicate handles to it for crash reporting. AddTargetPeer duplicates the + // handle, so we use a ScopedProcessHandle to automatically close ours. + ipc::ScopedProcessHandle parentProcHandle; + if (!base::OpenProcessHandle(OtherPid(), &parentProcHandle.rwget())) { + *aOutOk = false; + return IPC_OK(); + } + mSandboxBroker.AddTargetPeer(parentProcHandle); + + if (!mSandboxBroker.SetSecurityLevelForGMPlugin( + AbstractSandboxBroker::SandboxLevel(aParams.sandboxLevel()), + /* aIsRemoteLaunch */ true)) { + *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(), nullptr, (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 0000000000..7fa361f56f --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h @@ -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/. */ + +#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(mozilla::ipc::UntypedEndpoint&& aEndpoint); + + private: + mozilla::ipc::IPCResult RecvLaunchApp(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 0000000000..f8f3c60918 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp @@ -0,0 +1,81 @@ +/* -*- 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 <windows.h> + +namespace mozilla { + +RefPtr<GenericPromise> RemoteSandboxBrokerParent::Launch( + const nsTArray<uint64_t>& aHandlesToShare, nsISerialEventTarget* aThread) { + 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 = mProcess->TakeInitialEndpoint().Bind(this); + 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(aThread, __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, + nsDependentCString(XRE_GeckoProcessTypeToString( + GeckoProcessType_RemoteSandboxBroker)), + 1); + GenerateCrashReport(OtherPid()); + } + Shutdown(); +} + +void RemoteSandboxBrokerParent::Shutdown() { + if (mOpened) { + mOpened = false; + Close(); + } + if (mProcess) { + mProcess->Destroy(); + mProcess = nullptr; + } +} + +} // 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 0000000000..c0ebd786d2 --- /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/CrashReporterHelper.h" + +namespace mozilla { + +class RemoteSandboxBrokerParent + : public PRemoteSandboxBrokerParent, + public ipc::CrashReporterHelper<GeckoProcessType_RemoteSandboxBroker> { + 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. + // aThread is the thread to use to resolve the promise on if needed. + RefPtr<GenericPromise> Launch(const nsTArray<uint64_t>& aHandlesToShare, + nsISerialEventTarget* aThread); + + private: + void ActorDestroy(ActorDestroyReason aWhy) override; + + RemoteSandboxBrokerProcessParent* mProcess = nullptr; + + bool mOpened = false; +}; + +} // 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 0000000000..166b1d16a3 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp @@ -0,0 +1,27 @@ +/* -*- 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() {} + +bool RemoteSandboxBrokerProcessChild::Init(int aArgc, char* aArgv[]) { + BackgroundHangMonitor::Startup(); + return mSandboxBrokerChild.Init(TakeInitialEndpoint()); +} + +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 0000000000..b0a155b7b6 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.h @@ -0,0 +1,32 @@ +/* -*- 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: + using ProcessChild::ProcessChild; + ~RemoteSandboxBrokerProcessChild(); + + bool Init(int aArgc, char* aArgv[]) override; + void CleanUp() override; + + private: + RemoteSandboxBrokerChild mSandboxBrokerChild; +}; + +} // 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 0000000000..0bd40e88d6 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.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 "RemoteSandboxBrokerProcessParent.h" +#include <windows.h> + +using mozilla::ipc::GeckoChildProcessHost; +using mozilla::ipc::LaunchError; +using mozilla::ipc::ProcessHandlePromise; + +namespace mozilla { + +RemoteSandboxBrokerProcessParent::RemoteSandboxBrokerProcessParent() + : GeckoChildProcessHost(GeckoProcessType_RemoteSandboxBroker) { + MOZ_COUNT_CTOR(RemoteSandboxBrokerProcessParent); +} + +RemoteSandboxBrokerProcessParent::~RemoteSandboxBrokerProcessParent() { + MOZ_COUNT_DTOR(RemoteSandboxBrokerProcessParent); +} + +RefPtr<ProcessHandlePromise> RemoteSandboxBrokerProcessParent::AsyncLaunch() { + if (!GeckoChildProcessHost::AsyncLaunch()) { + return ProcessHandlePromise::CreateAndReject(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 0000000000..6b298ee9c6 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.h @@ -0,0 +1,41 @@ +/* -*- 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: + RemoteSandboxBrokerProcessParent(); + + RefPtr<ipc::ProcessHandlePromise> 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 0000000000..b0c715ce9d --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/moz.build @@ -0,0 +1,33 @@ +# -*- 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 0000000000..6f9f4233c6 --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp @@ -0,0 +1,171 @@ +/* -*- 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" + +#include "mozilla/SpinEventLoopUntil.h" +#include "nsIThread.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<RemoteSandboxBroker> 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, const IMAGE_THUNK_DATA*, void** aProcessHandle) { + // Note: we expect to be called on the IPC launch thread from + // GeckoChildProcesHost while it's launching a child process. The IPC launch + // thread is a TaskQueue. 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 = GetCurrentSerialEventTarget(); + + 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__); + }; + + // We need to wait on the current thread for the process to launch which will + // block the running IPC Launch taskqueue. We cannot use + // GetCurrentSerialEventTarget() (as this returns the currently running + // TaskQueue) to resolve our promise as it will be blocked until we return + // from this function. + nsCOMPtr<nsISerialEventTarget> target = NS_GetCurrentThread(); + mParent.Launch(mParameters.shareHandles(), target) + ->Then(target, __func__, std::move(resolve), std::move(reject)); + + // Spin the event loop while the sandbox launcher process launches. + SpinEventLoopUntil("RemoteSandboxBroker::LaunchApp"_ns, + [&]() { return res != Pending; }); + + if (res == Failed) { + return false; + } + + uint64_t handle = 0; + bool ok = false; + bool rv = mParent.SendLaunchApp(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, + bool aIsRemoteLaunch) { + 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)); +} + +void RemoteSandboxBroker::SetSecurityLevelForContentProcess( + int32_t aSandboxLevel, bool aIsFileProcess) { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForContentProcess not Implemented"); +} + +void RemoteSandboxBroker::SetSecurityLevelForGPUProcess( + int32_t aSandboxLevel, const nsCOMPtr<nsIFile>& aProfileDir) { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForGPUProcess not Implemented"); +} + +bool RemoteSandboxBroker::SetSecurityLevelForRDDProcess() { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForRDDProcess not Implemented"); +} + +bool RemoteSandboxBroker::SetSecurityLevelForSocketProcess() { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForSocketProcess not Implemented"); +} + +bool RemoteSandboxBroker::SetSecurityLevelForUtilityProcess( + mozilla::ipc::SandboxingKind aSandbox) { + MOZ_CRASH( + "RemoteSandboxBroker::SetSecurityLevelForUtilityProcess 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 0000000000..aee84ee43d --- /dev/null +++ b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.h @@ -0,0 +1,70 @@ +/* -*- 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, + const IMAGE_THUNK_DATA*, void** aProcessHandle) override; + + // Security levels for different types of processes + void SetSecurityLevelForContentProcess(int32_t aSandboxLevel, + bool aIsFileProcess) override; + void SetSecurityLevelForGPUProcess( + int32_t aSandboxLevel, const nsCOMPtr<nsIFile>& aProfileDir) override; + bool SetSecurityLevelForRDDProcess() override; + bool SetSecurityLevelForSocketProcess() override; + bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel, + bool aIsRemoteLaunch = false) override; + bool SetSecurityLevelForUtilityProcess( + mozilla::ipc::SandboxingKind aSandbox) override; + bool AllowReadFile(wchar_t const* file) override; + void AddHandleToShare(HANDLE aHandle) override; + + bool IsWin32kLockedDown() final { return false; }; + + 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<nsISerialEventTarget> mIPCLaunchThread; + + // True if we've been shutdown. + bool mShutdown = false; +}; + +} // namespace mozilla + +#endif // __REMOTE_SANDBOXBROKER_H__ |