зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1498742 - Part 2 - Start the GMP sandbox earlier during process startup r=jya,cpearce
Change the Mac GMP process launch to include sandboxing params on the command line to allow the sandbox to be started earlier during GMP process launch. Content, extension, and RDD processes have already been changed to start the sandbox earlier. Update GMPProcessParent to override GeckoChildProcessHost methods used to construct sandboxing parameters. Pass the plugin path as a sandbox parameter so that the sandbox rules can whitelist the plugin directory which is now read after the sandbox is enabled in the plugin process. On development builds, pass "testingReadPath" params so directories needed during automated tests can be whitelisted. Update Mac sandboxing code to detect GMP sandbox params on the command line and enable the sandbox with additional arguments needed for early sandbox start. Allow reverting to the old implementation by setting security.sandbox.gmp.mac.earlyinit to false. Differential Revision: https://phabricator.services.mozilla.com/D34085 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
fa1979ab86
Коммит
f87e72036e
|
@ -1066,6 +1066,8 @@ pref("security.sandbox.gmp.win32k-disable", false);
|
|||
pref("security.sandbox.content.mac.earlyinit", true);
|
||||
// Remove this pref once RDD early init is stable on Release.
|
||||
pref("security.sandbox.rdd.mac.earlyinit", true);
|
||||
// Remove this pref once GMP early init is stable on Release.
|
||||
pref("security.sandbox.gmp.mac.earlyinit", true);
|
||||
|
||||
// This pref is discussed in bug 1083344, the naming is inspired from its
|
||||
// Windows counterpart, but on Mac it's an integer which means:
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "gmp-video-decode.h"
|
||||
#include "gmp-video-encode.h"
|
||||
#include "GMPPlatform.h"
|
||||
#include "GMPProcessParent.h"
|
||||
#include "mozilla/Algorithm.h"
|
||||
#include "mozilla/ipc/CrashReporterClient.h"
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
|
@ -560,16 +561,22 @@ mozilla::ipc::IPCResult GMPChild::AnswerStartPlugin(const nsString& aAdapter) {
|
|||
return IPC_FAIL(this, "Can't sandbox GMP.");
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isChromium = aAdapter.EqualsLiteral("chromium");
|
||||
#if defined(MOZ_SANDBOX) && defined(XP_MACOSX)
|
||||
// Use of the chromium adapter indicates we are going to be
|
||||
// running the Widevine plugin which requires access to the
|
||||
// WindowServer in the Mac GMP sandbox policy.
|
||||
if (!SetMacSandboxInfo(isChromium /* allow-window-server */)) {
|
||||
NS_WARNING("Failed to set Mac GMP sandbox info");
|
||||
delete platformAPI;
|
||||
return IPC_FAIL(
|
||||
this, nsPrintfCString("Failed to set Mac GMP sandbox info.").get());
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
// If we started the sandbox at launch ("earlyinit"), then we don't
|
||||
// need to setup sandbox arguments here with SetMacSandboxInfo().
|
||||
if (!IsMacSandboxStarted()) {
|
||||
// Use of the chromium adapter indicates we are going to be
|
||||
// running the Widevine plugin which requires access to the
|
||||
// WindowServer in the Mac GMP sandbox policy.
|
||||
if (!SetMacSandboxInfo(isChromium /* allow-window-server */)) {
|
||||
NS_WARNING("Failed to set Mac GMP sandbox info");
|
||||
delete platformAPI;
|
||||
return IPC_FAIL(
|
||||
this, nsPrintfCString("Failed to set Mac GMP sandbox info.").get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -160,6 +160,12 @@ class WinSandboxStarter : public mozilla::gmp::SandboxStarter {
|
|||
class MacSandboxStarter : public mozilla::gmp::SandboxStarter {
|
||||
public:
|
||||
bool Start(const char* aLibPath) override {
|
||||
// If we started the sandbox at launch ("earlyinit"),
|
||||
// then don't try to start the sandbox again.
|
||||
if (IsMacSandboxStarted()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string err;
|
||||
bool rv = mozilla::StartMacSandbox(mInfo, err);
|
||||
if (!rv) {
|
||||
|
|
|
@ -149,6 +149,9 @@ nsresult GMPParent::LoadProcess() {
|
|||
|
||||
if (!mProcess) {
|
||||
mProcess = new GMPProcessParent(NS_ConvertUTF16toUTF8(path).get());
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
mProcess->SetRequiresWindowServer(mAdapter.EqualsLiteral("chromium"));
|
||||
#endif
|
||||
if (!mProcess->Launch(30 * 1000)) {
|
||||
LOGD("%s: Failed to launch new child process", __FUNCTION__);
|
||||
mProcess->Delete();
|
||||
|
|
|
@ -18,6 +18,16 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
# include "mozilla/dom/ContentChild.h"
|
||||
# include "mozilla/Sandbox.h"
|
||||
# include "nsMacUtilsImpl.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
# include "mozilla/SandboxSettings.h"
|
||||
#endif /* XP_MACOSX */
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
|
@ -29,9 +39,47 @@ static const int kInvalidFd = -1;
|
|||
namespace mozilla {
|
||||
namespace gmp {
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
bool GMPProcessParent::sLaunchWithMacSandbox = true;
|
||||
bool GMPProcessParent::sMacSandboxGMPLogging = false;
|
||||
# if defined(DEBUG)
|
||||
bool GMPProcessParent::sIsMainThreadInitDone = false;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
/* static */
|
||||
void GMPProcessParent::InitStaticMainThread() {
|
||||
// The GMPProcessParent constructor is called off the
|
||||
// main thread. Do main thread initialization here.
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
sLaunchWithMacSandbox =
|
||||
Preferences::GetBool("security.sandbox.gmp.mac.earlyinit", true) &&
|
||||
(getenv("MOZ_DISABLE_GMP_SANDBOX") == nullptr);
|
||||
sMacSandboxGMPLogging =
|
||||
Preferences::GetBool("security.sandbox.logging.enabled") ||
|
||||
PR_GetEnv("MOZ_SANDBOX_GMP_LOGGING") || PR_GetEnv("MOZ_SANDBOX_LOGGING");
|
||||
GMP_LOG("GMPProcessParent::InitStaticMainThread: earlyinit=%s, logging=%s",
|
||||
sLaunchWithMacSandbox ? "true" : "false",
|
||||
sMacSandboxGMPLogging ? "true" : "false");
|
||||
# if defined(DEBUG)
|
||||
sIsMainThreadInitDone = true;
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
GMPProcessParent::GMPProcessParent(const std::string& aGMPPath)
|
||||
: GeckoChildProcessHost(GeckoProcessType_GMPlugin), mGMPPath(aGMPPath) {
|
||||
: GeckoChildProcessHost(GeckoProcessType_GMPlugin),
|
||||
mGMPPath(aGMPPath)
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
,
|
||||
mRequiresWindowServer(false)
|
||||
#endif
|
||||
{
|
||||
MOZ_COUNT_CTOR(GMPProcessParent);
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
MOZ_ASSERT(sIsMainThreadInitDone == true);
|
||||
#endif
|
||||
}
|
||||
|
||||
GMPProcessParent::~GMPProcessParent() { MOZ_COUNT_DTOR(GMPProcessParent); }
|
||||
|
@ -68,6 +116,21 @@ bool GMPProcessParent::Launch(int32_t aTimeoutMs) {
|
|||
}
|
||||
|
||||
args.push_back(WideToUTF8(wGMPPath));
|
||||
#elif defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
// Resolve symlinks in the plugin path. The sandbox prevents
|
||||
// resolving symlinks in the child process if access to link
|
||||
// source file is denied.
|
||||
nsAutoCString normalizedPath;
|
||||
nsresult rv = NormalizePath(mGMPPath.c_str(), normalizedPath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
GMP_LOG(
|
||||
"GMPProcessParent::Launch: "
|
||||
"plugin path normaliziation failed for path: %s",
|
||||
mGMPPath.c_str());
|
||||
args.push_back(mGMPPath);
|
||||
} else {
|
||||
args.push_back(normalizedPath.get());
|
||||
}
|
||||
#else
|
||||
args.push_back(mGMPPath);
|
||||
#endif
|
||||
|
@ -98,5 +161,108 @@ void GMPProcessParent::DoDelete() {
|
|||
Destroy();
|
||||
}
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
bool GMPProcessParent::IsMacSandboxLaunchEnabled() {
|
||||
return sLaunchWithMacSandbox;
|
||||
}
|
||||
|
||||
void GMPProcessParent::SetRequiresWindowServer(bool aRequiresWindowServer) {
|
||||
mRequiresWindowServer = aRequiresWindowServer;
|
||||
}
|
||||
|
||||
bool GMPProcessParent::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
aInfo.type = MacSandboxType_GMP;
|
||||
aInfo.hasWindowServer = mRequiresWindowServer;
|
||||
aInfo.shouldLog = (aInfo.shouldLog || sMacSandboxGMPLogging);
|
||||
nsAutoCString appPath;
|
||||
if (!nsMacUtilsImpl::GetAppPath(appPath)) {
|
||||
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: failed to get app path");
|
||||
return false;
|
||||
}
|
||||
aInfo.appPath.assign(appPath.get());
|
||||
|
||||
GMP_LOG(
|
||||
"GMPProcessParent::FillMacSandboxInfo: "
|
||||
"plugin dir path: %s",
|
||||
mGMPPath.c_str());
|
||||
nsCOMPtr<nsIFile> pluginDir;
|
||||
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(mGMPPath.c_str()), true,
|
||||
getter_AddRefs(pluginDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
GMP_LOG(
|
||||
"GMPProcessParent::FillMacSandboxInfo: "
|
||||
"NS_NewLocalFile failed for plugin dir, rv=%d",
|
||||
rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
rv = pluginDir->Normalize();
|
||||
if (NS_FAILED(rv)) {
|
||||
GMP_LOG(
|
||||
"GMPProcessParent::FillMacSandboxInfo: "
|
||||
"failed to normalize plugin dir path, rv=%d",
|
||||
rv);
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString resolvedPluginPath;
|
||||
pluginDir->GetNativePath(resolvedPluginPath);
|
||||
aInfo.pluginPath.assign(resolvedPluginPath.get());
|
||||
GMP_LOG(
|
||||
"GMPProcessParent::FillMacSandboxInfo: "
|
||||
"resolved plugin dir path: %s",
|
||||
resolvedPluginPath.get());
|
||||
|
||||
if (mozilla::IsDevelopmentBuild()) {
|
||||
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: IsDevelopmentBuild()=true");
|
||||
|
||||
// Repo dir
|
||||
nsCOMPtr<nsIFile> repoDir;
|
||||
rv = nsMacUtilsImpl::GetRepoDir(getter_AddRefs(repoDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: failed to get repo dir");
|
||||
return false;
|
||||
}
|
||||
nsCString repoDirPath;
|
||||
Unused << repoDir->GetNativePath(repoDirPath);
|
||||
aInfo.testingReadPath1 = repoDirPath.get();
|
||||
GMP_LOG(
|
||||
"GMPProcessParent::FillMacSandboxInfo: "
|
||||
"repo dir path: %s",
|
||||
repoDirPath.get());
|
||||
|
||||
// Object dir
|
||||
nsCOMPtr<nsIFile> objDir;
|
||||
rv = nsMacUtilsImpl::GetObjDir(getter_AddRefs(objDir));
|
||||
if (NS_FAILED(rv)) {
|
||||
GMP_LOG("GMPProcessParent::FillMacSandboxInfo: failed to get object dir");
|
||||
return false;
|
||||
}
|
||||
nsCString objDirPath;
|
||||
Unused << objDir->GetNativePath(objDirPath);
|
||||
aInfo.testingReadPath2 = objDirPath.get();
|
||||
GMP_LOG(
|
||||
"GMPProcessParent::FillMacSandboxInfo: "
|
||||
"object dir path: %s",
|
||||
objDirPath.get());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult GMPProcessParent::NormalizePath(const char* aPath,
|
||||
nsACString& aNormalizedPath) {
|
||||
nsCOMPtr<nsIFile> fileOrDir;
|
||||
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(aPath), true,
|
||||
getter_AddRefs(fileOrDir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = fileOrDir->Normalize();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
fileOrDir->GetNativePath(aNormalizedPath);
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace gmp
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -32,6 +32,28 @@ class GMPProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
|
|||
bool CanShutdown() override { return true; }
|
||||
const std::string& GetPluginFilePath() { return mGMPPath; }
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
// Init static members on the main thread
|
||||
static void InitStaticMainThread();
|
||||
|
||||
// Read prefs and environment variables to determine
|
||||
// when and if to start the Mac sandbox for the child
|
||||
// process. Starting the sandbox at launch is the new
|
||||
// preferred method. Code to support starting the sandbox
|
||||
// later at plugin start time should be removed once
|
||||
// starting at launch is stable and shipping.
|
||||
bool IsMacSandboxLaunchEnabled() override;
|
||||
|
||||
// For process sandboxing purposes, set whether or not this
|
||||
// instance of the GMP process requires access to the macOS
|
||||
// window server. At present, Widevine requires window server
|
||||
// access, but OpenH264 decoding does not.
|
||||
void SetRequiresWindowServer(bool aRequiresWindowServer);
|
||||
|
||||
// Return the sandbox type to be used with this process type.
|
||||
static MacSandboxType GetMacSandboxType() { return MacSandboxType_GMP; };
|
||||
#endif
|
||||
|
||||
using mozilla::ipc::GeckoChildProcessHost::GetChannel;
|
||||
using mozilla::ipc::GeckoChildProcessHost::GetChildProcessHandle;
|
||||
|
||||
|
@ -43,6 +65,36 @@ class GMPProcessParent final : public mozilla::ipc::GeckoChildProcessHost {
|
|||
std::string mGMPPath;
|
||||
nsCOMPtr<nsIRunnable> mDeletedCallback;
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
// Indicates whether we'll start the Mac GMP sandbox during
|
||||
// process launch (earlyinit) which is the new preferred method
|
||||
// or later in the process lifetime.
|
||||
static bool sLaunchWithMacSandbox;
|
||||
|
||||
// Whether or not Mac sandbox violation logging is enabled.
|
||||
static bool sMacSandboxGMPLogging;
|
||||
|
||||
// Override so we can set GMP-specific sandbox parameters
|
||||
bool FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
|
||||
|
||||
// For normalizing paths to be compatible with sandboxing.
|
||||
// We use normalized paths to generate the sandbox ruleset. Once
|
||||
// the sandbox has been started, resolving symlinks that point to
|
||||
// allowed directories could require reading paths not allowed by
|
||||
// the sandbox, so we should only attempt to load plugin libraries
|
||||
// using normalized paths.
|
||||
static nsresult NormalizePath(const char* aPath, nsACString& aNormalizedPath);
|
||||
|
||||
// Controls whether or not the sandbox will be configured with
|
||||
// window service access.
|
||||
bool mRequiresWindowServer;
|
||||
|
||||
# if defined(DEBUG)
|
||||
// Used to assert InitStaticMainThread() is called before the constructor.
|
||||
static bool sIsMainThreadInitDone;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GMPProcessParent);
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "GMPVideoDecoderParent.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "GeckoChildProcessHost.h"
|
||||
#include "GMPProcessParent.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/SyncRunnable.h"
|
||||
#include "nsXPCOMPrivate.h"
|
||||
|
@ -102,13 +103,17 @@ class GMPServiceCreateHelper final : public mozilla::Runnable {
|
|||
new GeckoMediaPluginServiceParent();
|
||||
service->Init();
|
||||
sSingletonService = service;
|
||||
#if defined(XP_MACOSX)
|
||||
// GMPProcessParent should only be instantiated in the parent
|
||||
// so initialization only needs to be done in the parent.
|
||||
GMPProcessParent::InitStaticMainThread();
|
||||
#endif
|
||||
} else {
|
||||
RefPtr<GeckoMediaPluginServiceChild> service =
|
||||
new GeckoMediaPluginServiceChild();
|
||||
service->Init();
|
||||
sSingletonService = service;
|
||||
}
|
||||
|
||||
ClearOnShutdown(&sSingletonService);
|
||||
}
|
||||
|
||||
|
|
|
@ -261,15 +261,16 @@ void RDDProcessHost::DestroyProcess() {
|
|||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
/* static */
|
||||
void RDDProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
bool RDDProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
GeckoChildProcessHost::StaticFillMacSandboxInfo(aInfo);
|
||||
if (!aInfo.shouldLog && PR_GetEnv("MOZ_SANDBOX_RDD_LOGGING")) {
|
||||
aInfo.shouldLog = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void RDDProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
RDDProcessHost::StaticFillMacSandboxInfo(aInfo);
|
||||
bool RDDProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
return RDDProcessHost::StaticFillMacSandboxInfo(aInfo);
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -99,7 +99,7 @@ class RDDProcessHost final : public mozilla::ipc::GeckoChildProcessHost {
|
|||
// To allow filling a MacSandboxInfo from the child
|
||||
// process without an instance of RDDProcessHost.
|
||||
// Only needed for late-start sandbox enabling.
|
||||
static void StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
|
||||
static bool StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
|
||||
|
||||
// Return the sandbox type to be used with this process type.
|
||||
static MacSandboxType GetMacSandboxType();
|
||||
|
@ -130,7 +130,7 @@ class RDDProcessHost final : public mozilla::ipc::GeckoChildProcessHost {
|
|||
bool IsMacSandboxLaunchEnabled() override { return sLaunchWithMacSandbox; }
|
||||
|
||||
// Override so we can turn on RDD process-specific sandbox logging
|
||||
void FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
|
||||
bool FillMacSandboxInfo(MacSandboxInfo& aInfo) override;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RDDProcessHost);
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
# include "GMPProcessParent.h"
|
||||
# include "nsMacUtilsImpl.h"
|
||||
#endif
|
||||
|
||||
|
@ -370,8 +371,8 @@ bool GeckoChildProcessHost::AsyncLaunch(std::vector<std::string> aExtraOpts) {
|
|||
PrepareLaunch();
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
if (IsMacSandboxLaunchEnabled()) {
|
||||
AppendMacSandboxParams(aExtraOpts);
|
||||
if (IsMacSandboxLaunchEnabled() && !AppendMacSandboxParams(aExtraOpts)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1397,15 +1398,18 @@ void GeckoChildProcessHost::LaunchAndroidService(
|
|||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
void GeckoChildProcessHost::AppendMacSandboxParams(StringVector& aArgs) {
|
||||
bool GeckoChildProcessHost::AppendMacSandboxParams(StringVector& aArgs) {
|
||||
MacSandboxInfo info;
|
||||
FillMacSandboxInfo(info);
|
||||
if (!FillMacSandboxInfo(info)) {
|
||||
return false;
|
||||
}
|
||||
info.AppendAsParams(aArgs);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fill |aInfo| with the flags needed to launch the utility sandbox
|
||||
/* static */
|
||||
void GeckoChildProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
bool GeckoChildProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
aInfo.type = GetDefaultMacSandboxType();
|
||||
aInfo.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
|
||||
PR_GetEnv("MOZ_SANDBOX_LOGGING");
|
||||
|
@ -1415,10 +1419,11 @@ void GeckoChildProcessHost::StaticFillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
|||
MOZ_CRASH("Failed to get app path");
|
||||
}
|
||||
aInfo.appPath.assign(appPath.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
void GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
GeckoChildProcessHost::StaticFillMacSandboxInfo(aInfo);
|
||||
bool GeckoChildProcessHost::FillMacSandboxInfo(MacSandboxInfo& aInfo) {
|
||||
return GeckoChildProcessHost::StaticFillMacSandboxInfo(aInfo);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -1432,9 +1437,9 @@ bool GeckoChildProcessHost::StartMacSandbox(int aArgc, char** aArgv,
|
|||
std::string& aErrorMessage) {
|
||||
MacSandboxType sandboxType = MacSandboxType_Invalid;
|
||||
switch (XRE_GetProcessType()) {
|
||||
// For now, only support early sandbox startup for content
|
||||
// processes. Add case statements for the additional process
|
||||
// types once early sandbox startup is implemented for them.
|
||||
// For now, only support early sandbox startup for content,
|
||||
// RDD, and GMP processes. Add case statements for the additional
|
||||
// process types once early sandbox startup is implemented for them.
|
||||
case GeckoProcessType_Content:
|
||||
// Content processes don't use GeckoChildProcessHost
|
||||
// to configure sandboxing so hard code the sandbox type.
|
||||
|
@ -1443,6 +1448,9 @@ bool GeckoChildProcessHost::StartMacSandbox(int aArgc, char** aArgv,
|
|||
case GeckoProcessType_RDD:
|
||||
sandboxType = RDDProcessHost::GetMacSandboxType();
|
||||
break;
|
||||
case GeckoProcessType_GMPlugin:
|
||||
sandboxType = gmp::GMPProcessParent::GetMacSandboxType();
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ class GeckoChildProcessHost : public ChildProcessHost {
|
|||
// To allow filling a MacSandboxInfo from the child
|
||||
// process without an instance of RDDProcessHost.
|
||||
// Only needed for late-start sandbox enabling.
|
||||
static void StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
|
||||
static bool StaticFillMacSandboxInfo(MacSandboxInfo& aInfo);
|
||||
|
||||
// Start the sandbox from the child process.
|
||||
static bool StartMacSandbox(int aArgc, char** aArgv,
|
||||
|
@ -215,12 +215,12 @@ class GeckoChildProcessHost : public ChildProcessHost {
|
|||
virtual bool IsMacSandboxLaunchEnabled() { return false; }
|
||||
|
||||
// Fill a MacSandboxInfo to configure the sandbox
|
||||
virtual void FillMacSandboxInfo(MacSandboxInfo& aInfo);
|
||||
virtual bool FillMacSandboxInfo(MacSandboxInfo& aInfo);
|
||||
|
||||
// Adds the command line arguments needed to enable
|
||||
// sandboxing of the child process at startup before
|
||||
// the child event loop is up.
|
||||
virtual void AppendMacSandboxParams(StringVector& aArgs);
|
||||
virtual bool AppendMacSandboxParams(StringVector& aArgs);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
|
@ -36,6 +36,7 @@ typedef struct _MacSandboxInfo {
|
|||
void AppendStartupParam(std::vector<std::string>& aParams) const;
|
||||
void AppendLoggingParam(std::vector<std::string>& aParams) const;
|
||||
void AppendAppPathParam(std::vector<std::string>& aParams) const;
|
||||
void AppendPluginPathParam(std::vector<std::string>& aParams) const;
|
||||
void AppendLevelParam(std::vector<std::string>& aParams) const;
|
||||
void AppendAudioParam(std::vector<std::string>& aParams) const;
|
||||
void AppendWindowServerParam(std::vector<std::string>& aParams) const;
|
||||
|
@ -76,6 +77,7 @@ namespace mozilla {
|
|||
bool StartMacSandbox(MacSandboxInfo const& aInfo, std::string& aErrorMessage);
|
||||
bool StartMacSandboxIfEnabled(MacSandboxType aSandboxType, int aArgc,
|
||||
char** aArgv, std::string& aErrorMessage);
|
||||
bool IsMacSandboxStarted();
|
||||
#ifdef DEBUG
|
||||
void AssertMacSandboxEnabled();
|
||||
#endif /* DEBUG */
|
||||
|
|
|
@ -33,9 +33,7 @@ extern "C" int sandbox_init(const char* profile, uint64_t flags, char** errorbuf
|
|||
extern "C" int sandbox_init_with_parameters(const char* profile, uint64_t flags,
|
||||
const char* const parameters[], char** errorbuf);
|
||||
extern "C" void sandbox_free_error(char* errorbuf);
|
||||
#ifdef DEBUG
|
||||
extern "C" int sandbox_check(pid_t pid, const char* operation, int type, ...);
|
||||
#endif
|
||||
|
||||
#define MAC_OS_X_VERSION_10_0_HEX 0x00001000
|
||||
#define MAC_OS_X_VERSION_10_6_HEX 0x00001060
|
||||
|
@ -151,6 +149,11 @@ void MacSandboxInfo::AppendAsParams(std::vector<std::string>& aParams) const {
|
|||
break;
|
||||
case MacSandboxType_Utility:
|
||||
break;
|
||||
case MacSandboxType_GMP:
|
||||
this->AppendPluginPathParam(aParams);
|
||||
this->AppendWindowServerParam(aParams);
|
||||
this->AppendReadPathParams(aParams);
|
||||
break;
|
||||
default:
|
||||
// Before supporting a new process type, add a case statement
|
||||
// here to append any neccesary process-type-specific params.
|
||||
|
@ -174,6 +177,11 @@ void MacSandboxInfo::AppendAppPathParam(std::vector<std::string>& aParams) const
|
|||
aParams.push_back(this->appPath);
|
||||
}
|
||||
|
||||
void MacSandboxInfo::AppendPluginPathParam(std::vector<std::string>& aParams) const {
|
||||
aParams.push_back("-sbPluginPath");
|
||||
aParams.push_back(this->pluginPath);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void MacSandboxInfo::AppendFileAccessParam(std::vector<std::string>& aParams,
|
||||
bool aHasFilePrivileges) {
|
||||
|
@ -298,14 +306,28 @@ bool StartMacSandbox(MacSandboxInfo const& aInfo, std::string& aErrorMessage) {
|
|||
profile = const_cast<char*>(SandboxPolicyGMP);
|
||||
params.push_back("SHOULD_LOG");
|
||||
params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
|
||||
params.push_back("PLUGIN_BINARY_PATH");
|
||||
params.push_back(aInfo.pluginBinaryPath.c_str());
|
||||
params.push_back("APP_PATH");
|
||||
params.push_back(aInfo.appPath.c_str());
|
||||
params.push_back("APP_BINARY_PATH");
|
||||
params.push_back(aInfo.appBinaryPath.c_str());
|
||||
params.push_back("PLUGIN_PATH");
|
||||
params.push_back(aInfo.pluginPath.c_str());
|
||||
if (!aInfo.pluginBinaryPath.empty()) {
|
||||
params.push_back("PLUGIN_BINARY_PATH");
|
||||
params.push_back(aInfo.pluginBinaryPath.c_str());
|
||||
}
|
||||
params.push_back("HAS_WINDOW_SERVER");
|
||||
params.push_back(aInfo.hasWindowServer ? "TRUE" : "FALSE");
|
||||
if (!aInfo.crashServerPort.empty()) {
|
||||
params.push_back("CRASH_PORT");
|
||||
params.push_back(aInfo.crashServerPort.c_str());
|
||||
}
|
||||
if (!aInfo.testingReadPath1.empty()) {
|
||||
params.push_back("TESTING_READ_PATH1");
|
||||
params.push_back(aInfo.testingReadPath1.c_str());
|
||||
}
|
||||
if (!aInfo.testingReadPath2.empty()) {
|
||||
params.push_back("TESTING_READ_PATH2");
|
||||
params.push_back(aInfo.testingReadPath2.c_str());
|
||||
}
|
||||
} else if (aInfo.type == MacSandboxType_Content) {
|
||||
MOZ_ASSERT(aInfo.level >= 1);
|
||||
if (aInfo.level >= 1) {
|
||||
|
@ -433,7 +455,7 @@ bool GetContentSandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aI
|
|||
|
||||
// Read access directories used in testing
|
||||
int nTestingReadPaths = 0;
|
||||
std::string testingReadPaths[MAX_TESTING_READ_PATHS] = {};
|
||||
std::string testingReadPaths[MAX_CONTENT_TESTING_READ_PATHS] = {};
|
||||
|
||||
// Collect sandbox params from CLI arguments
|
||||
for (int i = 0; i < aArgc; i++) {
|
||||
|
@ -479,7 +501,9 @@ bool GetContentSandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aI
|
|||
}
|
||||
|
||||
if ((strcmp(aArgv[i], "-sbTestingReadPath") == 0) && (i + 1 < aArgc)) {
|
||||
MOZ_ASSERT(nTestingReadPaths < MAX_TESTING_READ_PATHS);
|
||||
if (nTestingReadPaths >= MAX_CONTENT_TESTING_READ_PATHS) {
|
||||
MOZ_CRASH("Too many content process -sbTestingReadPath arguments");
|
||||
}
|
||||
testingReadPaths[nTestingReadPaths] = aArgv[i + 1];
|
||||
nTestingReadPaths++;
|
||||
i++;
|
||||
|
@ -571,6 +595,77 @@ bool GetUtilitySandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aI
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GetPluginSandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aInfo) {
|
||||
// Ensure we find these paramaters in the command
|
||||
// line arguments. Return false if any are missing.
|
||||
bool foundAppPath = false;
|
||||
bool foundPluginPath = false;
|
||||
|
||||
// Read access directories used in testing
|
||||
int nTestingReadPaths = 0;
|
||||
std::string testingReadPaths[MAX_GMP_TESTING_READ_PATHS] = {};
|
||||
|
||||
// Collect sandbox params from CLI arguments
|
||||
for (int i = 0; i < aArgc; i++) {
|
||||
if (strcmp(aArgv[i], "-sbLogging") == 0) {
|
||||
aInfo.shouldLog = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((strcmp(aArgv[i], "-sbAppPath") == 0) && (i + 1 < aArgc)) {
|
||||
foundAppPath = true;
|
||||
aInfo.appPath.assign(aArgv[i + 1]);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((strcmp(aArgv[i], "-sbPluginPath") == 0) && (i + 1 < aArgc)) {
|
||||
foundPluginPath = true;
|
||||
aInfo.pluginPath.assign(aArgv[i + 1]);
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(aArgv[i], "-sbAllowWindowServer") == 0) {
|
||||
aInfo.hasWindowServer = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((strcmp(aArgv[i], "-sbTestingReadPath") == 0) && (i + 1 < aArgc)) {
|
||||
if (nTestingReadPaths >= MAX_GMP_TESTING_READ_PATHS) {
|
||||
MOZ_CRASH("Too many GMP process -sbTestingReadPath arguments");
|
||||
}
|
||||
testingReadPaths[nTestingReadPaths] = aArgv[i + 1];
|
||||
nTestingReadPaths++;
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle crash server positional argument
|
||||
if (strstr(aArgv[i], "gecko-crash-server-pipe") != NULL) {
|
||||
aInfo.crashServerPort.assign(aArgv[i]);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundPluginPath) {
|
||||
fprintf(stderr, "GMP sandbox disabled due to "
|
||||
"missing sandbox CLI plugin path parameter.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!foundAppPath) {
|
||||
fprintf(stderr, "GMP sandbox disabled due to "
|
||||
"missing sandbox CLI app path parameter.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
aInfo.testingReadPath1 = testingReadPaths[0];
|
||||
aInfo.testingReadPath2 = testingReadPaths[1];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if no errors were encountered or if early sandbox startup is
|
||||
* not enabled for this process. Returns false if an error was encountered.
|
||||
|
@ -611,6 +706,11 @@ bool StartMacSandboxIfEnabled(const MacSandboxType aSandboxType, int aArgc, char
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case MacSandboxType_GMP:
|
||||
if (!GetPluginSandboxParamsFromArgs(aArgc, aArgv, info)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_RELEASE_ASSERT(false);
|
||||
break;
|
||||
|
@ -619,6 +719,8 @@ bool StartMacSandboxIfEnabled(const MacSandboxType aSandboxType, int aArgc, char
|
|||
return StartMacSandbox(info, aErrorMessage);
|
||||
}
|
||||
|
||||
bool IsMacSandboxStarted() { return sandbox_check(getpid(), NULL, 0) == 1; }
|
||||
|
||||
#ifdef DEBUG
|
||||
// sandbox_check returns 1 if the specified process is sandboxed
|
||||
void AssertMacSandboxEnabled() { MOZ_ASSERT(sandbox_check(getpid(), NULL, 0) == 1); }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#ifndef mozilla_SandboxPolicyContent_h
|
||||
#define mozilla_SandboxPolicyContent_h
|
||||
|
||||
#define MAX_TESTING_READ_PATHS 4
|
||||
#define MAX_CONTENT_TESTING_READ_PATHS 4
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -6,16 +6,21 @@
|
|||
#ifndef mozilla_SandboxPolicyGMP_h
|
||||
#define mozilla_SandboxPolicyGMP_h
|
||||
|
||||
#define MAX_GMP_TESTING_READ_PATHS 2
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static const char SandboxPolicyGMP[] = R"SANDBOX_LITERAL(
|
||||
(version 1)
|
||||
|
||||
(define should-log (param "SHOULD_LOG"))
|
||||
(define plugin-binary-path (param "PLUGIN_BINARY_PATH"))
|
||||
(define app-path (param "APP_PATH"))
|
||||
(define app-binary-path (param "APP_BINARY_PATH"))
|
||||
(define plugin-path (param "PLUGIN_PATH"))
|
||||
(define plugin-binary-path (param "PLUGIN_BINARY_PATH"))
|
||||
(define crashPort (param "CRASH_PORT"))
|
||||
(define hasWindowServer (param "HAS_WINDOW_SERVER"))
|
||||
(define testingReadPath1 (param "TESTING_READ_PATH1"))
|
||||
(define testingReadPath2 (param "TESTING_READ_PATH2"))
|
||||
|
||||
(define (moz-deny feature)
|
||||
(if (string=? should-log "TRUE")
|
||||
|
@ -34,18 +39,35 @@ static const char SandboxPolicyGMP[] = R"SANDBOX_LITERAL(
|
|||
|
||||
(if (defined? 'file-map-executable)
|
||||
(allow file-map-executable file-read*
|
||||
(subpath "/System/Library/PrivateFrameworks")
|
||||
(regex #"^/usr/lib/libstdc\+\+\.[^/]*dylib$")
|
||||
(literal plugin-binary-path)
|
||||
(literal app-binary-path)
|
||||
(subpath "/System/Library")
|
||||
(subpath "/usr/lib")
|
||||
(subpath plugin-path)
|
||||
(subpath app-path))
|
||||
(allow file-read*
|
||||
(subpath "/System/Library/PrivateFrameworks")
|
||||
(regex #"^/usr/lib/libstdc\+\+\.[^/]*dylib$")
|
||||
(literal plugin-binary-path)
|
||||
(literal app-binary-path)
|
||||
(subpath "/System/Library")
|
||||
(subpath "/usr/lib")
|
||||
(subpath plugin-path)
|
||||
(subpath app-path)))
|
||||
|
||||
(if (defined? 'file-map-executable)
|
||||
(begin
|
||||
(when plugin-binary-path
|
||||
(allow file-read* file-map-executable (subpath plugin-binary-path)))
|
||||
(when testingReadPath1
|
||||
(allow file-read* file-map-executable (subpath testingReadPath1)))
|
||||
(when testingReadPath2
|
||||
(allow file-read* file-map-executable (subpath testingReadPath2))))
|
||||
(begin
|
||||
(when plugin-binary-path
|
||||
(allow file-read* (subpath plugin-binary-path)))
|
||||
(when testingReadPath1
|
||||
(allow file-read* (subpath testingReadPath1)))
|
||||
(when testingReadPath2
|
||||
(allow file-read* (subpath testingReadPath2)))))
|
||||
|
||||
(if (string? crashPort)
|
||||
(allow mach-lookup (global-name crashPort)))
|
||||
|
||||
(allow signal (target self))
|
||||
(allow sysctl-read)
|
||||
(allow iokit-open (iokit-user-client-class "IOHIDParamUserClient"))
|
||||
|
@ -53,9 +75,7 @@ static const char SandboxPolicyGMP[] = R"SANDBOX_LITERAL(
|
|||
(literal "/etc")
|
||||
(literal "/dev/random")
|
||||
(literal "/dev/urandom")
|
||||
(literal "/usr/share/icu/icudt51l.dat")
|
||||
(subpath "/System/Library/Displays/Overrides")
|
||||
(subpath "/System/Library/CoreServices/CoreTypes.bundle"))
|
||||
(literal "/usr/share/icu/icudt51l.dat"))
|
||||
|
||||
(if (string=? hasWindowServer "TRUE")
|
||||
(allow mach-lookup (global-name "com.apple.windowserver.active")))
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "nsIFile.h"
|
||||
#include "nsIProperties.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "prenv.h"
|
||||
|
||||
|
@ -209,12 +210,25 @@ bool nsMacUtilsImpl::GetAppPath(nsCString& aAppPath) {
|
|||
|
||||
if (!sCachedAppPath) {
|
||||
sCachedAppPath = new nsCString(aAppPath);
|
||||
ClearOnShutdown(&sCachedAppPath);
|
||||
|
||||
if (NS_IsMainThread()) {
|
||||
nsMacUtilsImpl::ClearCachedAppPathOnShutdown();
|
||||
} else {
|
||||
NS_DispatchToMainThread(NS_NewRunnableFunction(
|
||||
"nsMacUtilsImpl::ClearCachedAppPathOnShutdown",
|
||||
[] { nsMacUtilsImpl::ClearCachedAppPathOnShutdown(); }));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult nsMacUtilsImpl::ClearCachedAppPathOnShutdown() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ClearOnShutdown(&sCachedAppPath);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to read a string value for a given key from the .app's
|
||||
* Info.plist.
|
||||
|
|
|
@ -58,6 +58,8 @@ class nsMacUtilsImpl final : public nsIMacUtils {
|
|||
static StaticAutoPtr<nsCString> sCachedAppPath;
|
||||
// For thread safe setting/checking of sCachedAppPath
|
||||
static StaticMutex sCachedAppPathMutex;
|
||||
// Utility method to call ClearOnShutdown() on the main thread
|
||||
static nsresult ClearCachedAppPathOnShutdown();
|
||||
#endif
|
||||
|
||||
enum TCSMStatus { TCSM_Unknown = 0, TCSM_Available, TCSM_Unavailable };
|
||||
|
|
Загрузка…
Ссылка в новой задаче