Backed out changeset e56421ffea4f (bug 1920463) Backed out changeset 3c3f9787cfe4 (bug 1920463)
168 lines
5.9 KiB
C++
168 lines
5.9 KiB
C++
/* -*- 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
|