Bug 1859708: Add rule to allow read access to the binary dir for GPU sandbox. r=cmartin

This also changes the way we populate the cached binary dir string, so that when
it is populated, it is done in SandboxBroker::Initialize.

Differential Revision: https://phabricator.services.mozilla.com/D205099
This commit is contained in:
Bob Owen 2024-03-19 22:09:10 +00:00
parent 23a339fc7c
commit 90e0706ca0
5 changed files with 43 additions and 40 deletions

View File

@ -1084,6 +1084,10 @@ int XRE_XPCShellMain(int argc, char** argv, char** envp,
// stability, we should instantiate COM ASAP so that we can ensure that these
// global settings are configured before anything can interfere.
mscom::ProcessRuntime mscom;
# ifdef MOZ_SANDBOX
nsAutoString binDirPath;
# endif
#endif
// The provider needs to outlive the call to shutting down XPCOM.
@ -1103,6 +1107,11 @@ int XRE_XPCShellMain(int argc, char** argv, char** envp,
return 1;
}
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
// We need the binary directory to initialize the windows sandbox.
MOZ_ALWAYS_SUCCEEDS(appDir->GetPath(binDirPath));
#endif
dirprovider.SetAppFile(appFile);
nsCOMPtr<nsIFile> greDir;
@ -1301,7 +1310,7 @@ int XRE_XPCShellMain(int argc, char** argv, char** envp,
# if defined(MOZ_SANDBOX)
// Required for sandboxed child processes.
if (aShellData->sandboxBrokerServices) {
SandboxBroker::Initialize(aShellData->sandboxBrokerServices);
SandboxBroker::Initialize(aShellData->sandboxBrokerServices, binDirPath);
SandboxBroker::GeckoDependentInitialize();
} else {
NS_WARNING(

View File

@ -30,7 +30,6 @@
#include "mozilla/Telemetry.h"
#include "mozilla/WinDllServices.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/WinHeaderOnlyUtils.h"
#include "mozilla/ipc/LaunchError.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsCOMPtr.h"
@ -116,11 +115,27 @@ static sandbox::ResultCode AddWin32kLockdownPolicy(
return result;
}
static void CacheDirAndAutoClear(const nsAString& aDir,
StaticAutoPtr<nsString>* cacheVar) {
*cacheVar = new nsString(aDir);
ClearOnShutdown(cacheVar);
// Convert network share path to format for sandbox policy.
if (Substring(**cacheVar, 0, 2).Equals(u"\\\\"_ns)) {
(*cacheVar)->InsertLiteral(u"??\\UNC", 1);
}
}
/* static */
void SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices) {
void SandboxBroker::Initialize(sandbox::BrokerServices* aBrokerServices,
const nsAString& aBinDir) {
sBrokerService = aBrokerServices;
sRunningFromNetworkDrive = widget::WinUtils::RunningFromANetworkDrive();
if (!aBinDir.IsEmpty()) {
CacheDirAndAutoClear(aBinDir, &sBinDir);
}
}
static void CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey,
@ -135,14 +150,9 @@ static void CacheDirAndAutoClear(nsIProperties* aDirSvc, const char* aDirKey,
return;
}
*cacheVar = new nsString();
ClearOnShutdown(cacheVar);
MOZ_ALWAYS_SUCCEEDS(dirToCache->GetPath(**cacheVar));
// Convert network share path to format for sandbox policy.
if (Substring(**cacheVar, 0, 2).Equals(u"\\\\"_ns)) {
(*cacheVar)->InsertLiteral(u"??\\UNC", 1);
}
nsAutoString dirPath;
MOZ_ALWAYS_SUCCEEDS(dirToCache->GetPath(dirPath));
CacheDirAndAutoClear(dirPath, cacheVar);
}
/* static */
@ -166,7 +176,6 @@ void SandboxBroker::GeckoDependentInitialize() {
return;
}
CacheDirAndAutoClear(dirSvc, NS_GRE_DIR, &sBinDir);
CacheDirAndAutoClear(dirSvc, NS_APP_USER_PROFILE_50_DIR, &sProfileDir);
CacheDirAndAutoClear(dirSvc, NS_WIN_LOCAL_APPDATA_DIR, &sLocalAppDataDir);
#ifdef ENABLE_SYSTEM_EXTENSION_DIRS
@ -481,33 +490,11 @@ static sandbox::ResultCode AllowProxyLoadFromBinDir(
sandbox::TargetPolicy* aPolicy) {
// Allow modules in the directory containing the executable such as
// mozglue.dll, nss3.dll, etc.
static UniquePtr<nsString> sInstallDir;
if (!sInstallDir) {
// Since this function can be called before sBinDir is initialized,
// we cache the install path by ourselves.
UniquePtr<wchar_t[]> appDirStr;
if (GetInstallDirectory(appDirStr)) {
sInstallDir = MakeUnique<nsString>(appDirStr.get());
sInstallDir->Append(u"\\*");
auto setClearOnShutdown = [ptr = &sInstallDir]() -> void {
ClearOnShutdown(ptr);
};
if (NS_IsMainThread()) {
setClearOnShutdown();
} else {
SchedulerGroup::Dispatch(NS_NewRunnableFunction(
"InitSignedPolicyRulesToBypassCig", std::move(setClearOnShutdown)));
}
}
if (!sInstallDir) {
return sandbox::SBOX_ERROR_GENERIC;
}
}
nsAutoString rulePath(*sBinDir);
rulePath.Append(u"\\*"_ns);
return aPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD,
sInstallDir->get());
rulePath.get());
}
static sandbox::ResultCode AddCigToPolicy(
@ -1084,6 +1071,10 @@ void SandboxBroker::SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) {
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*"));
// Add rule to allow read access to installation directory.
AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_READONLY,
sBinDir, u"\\*"_ns);
// The GPU process needs to write to a shader cache for performance reasons
if (sProfileDir) {
AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,

View File

@ -75,7 +75,8 @@ class SandboxBroker : public AbstractSandboxBroker {
public:
SandboxBroker();
static void Initialize(sandbox::BrokerServices* aBrokerServices);
static void Initialize(sandbox::BrokerServices* aBrokerServices,
const nsAString& aBinDir);
static void EnsureLpacPermsissionsOnDir(const nsString& aDir);

View File

@ -4224,7 +4224,9 @@ int XREMain::XRE_mainInit(bool* aExitFlag) {
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
if (mAppData->sandboxBrokerServices) {
SandboxBroker::Initialize(mAppData->sandboxBrokerServices);
nsAutoString binDirPath;
MOZ_ALWAYS_SUCCEEDS(xreBinDirectory->GetPath(binDirPath));
SandboxBroker::Initialize(mAppData->sandboxBrokerServices, binDirPath);
} else {
# if defined(MOZ_SANDBOX)
// If we're sandboxing content and we fail to initialize, then crashing here

View File

@ -525,7 +525,7 @@ nsresult XRE_InitChildProcess(int aArgc, char* aArgv[],
#if defined(XP_WIN)
# if defined(MOZ_SANDBOX)
if (aChildData->sandboxBrokerServices) {
SandboxBroker::Initialize(aChildData->sandboxBrokerServices);
SandboxBroker::Initialize(aChildData->sandboxBrokerServices, u""_ns);
SandboxBroker::GeckoDependentInitialize();
}
# endif // defined(MOZ_SANDBOX)