summaryrefslogtreecommitdiffstats
path: root/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp')
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp167
1 files changed, 167 insertions, 0 deletions
diff --git a/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp
new file mode 100644
index 0000000000..f898251d72
--- /dev/null
+++ b/security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp
@@ -0,0 +1,167 @@
+/* -*- 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 "RemoteSandboxBrokerParent.h"
+#include "mozilla/SpinEventLoopUntil.h"
+#include "nsIThread.h"
+
+namespace mozilla {
+
+RemoteSandboxBroker::RemoteSandboxBroker(uint32_t aLaunchArch)
+ : mParent(new RemoteSandboxBrokerParent), mLaunchArch(aLaunchArch) {}
+
+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;
+ }));
+}
+
+Result<Ok, mozilla::ipc::LaunchError> 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(mLaunchArch, 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 Err(mozilla::ipc::LaunchError("RSB::LaunchApp"));
+ }
+
+ uint64_t handle = 0;
+ bool ok = false;
+ bool rv = mParent->SendLaunchApp(std::move(mParameters), &ok, &handle) && ok;
+ mParameters.shareHandles().Clear();
+ if (!rv) {
+ mParent->Shutdown();
+ return Err(mozilla::ipc::LaunchError("RSB::SendLaunchApp"));
+ }
+
+ // 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) {
+ mParent->Shutdown();
+ return Err(mozilla::ipc::LaunchError("RSB::DuplicateFromLauncher"));
+ }
+
+ *aProcessHandle = (void**)(ourChildHandle);
+
+ return Ok();
+}
+
+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) {
+ 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");
+}
+
+} // namespace mozilla