summaryrefslogtreecommitdiffstats
path: root/security/sandbox/win/src/remotesandboxbroker
diff options
context:
space:
mode:
Diffstat (limited to 'security/sandbox/win/src/remotesandboxbroker')
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/PRemoteSandboxBroker.ipdl36
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.cpp96
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerChild.h33
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.cpp81
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerParent.h43
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.cpp27
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessChild.h32
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.cpp32
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/RemoteSandboxBrokerProcessParent.h41
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/moz.build33
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.cpp171
-rw-r--r--security/sandbox/win/src/remotesandboxbroker/remoteSandboxBroker.h70
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__