Bug 1799470 - Retighten GPU Process File Access r=nika,handyman

Differential Revision: https://phabricator.services.mozilla.com/D165419
This commit is contained in:
Chris Martin 2023-01-23 23:05:03 +00:00
parent f822f99642
commit 15c5b22789
10 changed files with 61 additions and 68 deletions

View file

@ -253,7 +253,6 @@ class WindowsProcessLauncher : public BaseProcessLauncher {
WindowsProcessLauncher(GeckoChildProcessHost* aHost, WindowsProcessLauncher(GeckoChildProcessHost* aHost,
std::vector<std::string>&& aExtraOpts) std::vector<std::string>&& aExtraOpts)
: BaseProcessLauncher(aHost, std::move(aExtraOpts)), : BaseProcessLauncher(aHost, std::move(aExtraOpts)),
mProfileDir(aHost->mProfileDir),
mCachedNtdllThunk(GetCachedNtDllThunk()), mCachedNtdllThunk(GetCachedNtDllThunk()),
mWerDataPointer(&(aHost->mWerData)) {} mWerDataPointer(&(aHost->mWerData)) {}
@ -266,8 +265,6 @@ class WindowsProcessLauncher : public BaseProcessLauncher {
mozilla::Maybe<CommandLine> mCmdLine; mozilla::Maybe<CommandLine> mCmdLine;
bool mUseSandbox = false; bool mUseSandbox = false;
nsCOMPtr<nsIFile> mProfileDir;
const Buffer<IMAGE_THUNK_DATA>* mCachedNtdllThunk; const Buffer<IMAGE_THUNK_DATA>* mCachedNtdllThunk;
CrashReporter::WindowsErrorReportingData const* mWerDataPointer; CrashReporter::WindowsErrorReportingData const* mWerDataPointer;
}; };
@ -643,10 +640,6 @@ void GeckoChildProcessHost::PrepareLaunch() {
mEnableSandboxLogging = mEnableSandboxLogging =
mEnableSandboxLogging || !!PR_GetEnv("MOZ_SANDBOX_LOGGING"); mEnableSandboxLogging || !!PR_GetEnv("MOZ_SANDBOX_LOGGING");
if (ShouldHaveDirectoryService() && mProcessType == GeckoProcessType_GPU) {
mozilla::Unused << NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
getter_AddRefs(mProfileDir));
}
# endif # endif
#elif defined(XP_MACOSX) #elif defined(XP_MACOSX)
# if defined(MOZ_SANDBOX) # if defined(MOZ_SANDBOX)
@ -1435,8 +1428,7 @@ bool WindowsProcessLauncher::DoSetup() {
// For now we treat every failure as fatal in // For now we treat every failure as fatal in
// SetSecurityLevelForGPUProcess and just crash there right away. Should // SetSecurityLevelForGPUProcess and just crash there right away. Should
// this change in the future then we should also handle the error here. // this change in the future then we should also handle the error here.
mResults.mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel, mResults.mSandboxBroker->SetSecurityLevelForGPUProcess(mSandboxLevel);
mProfileDir);
mUseSandbox = true; mUseSandbox = true;
} }
break; break;

View file

@ -81,6 +81,10 @@ void SandboxTestingChild::Bind(Endpoint<PSandboxTestingChild>&& aEndpoint) {
RunTestsSocket(this); RunTestsSocket(this);
} }
if (XRE_IsGPUProcess()) {
RunTestsGPU(this);
}
if (XRE_IsUtilityProcess()) { if (XRE_IsUtilityProcess()) {
RefPtr<ipc::UtilityProcessChild> s = ipc::UtilityProcessChild::Get(); RefPtr<ipc::UtilityProcessChild> s = ipc::UtilityProcessChild::Get();
MOZ_ASSERT(s, "Unable to grab a UtilityProcessChild"); MOZ_ASSERT(s, "Unable to grab a UtilityProcessChild");

View file

@ -821,4 +821,24 @@ void RunTestsUtilityAudioDecoder(SandboxTestingChild* child,
#endif // XP_UNIX #endif // XP_UNIX
} }
void RunTestsGPU(SandboxTestingChild* child) {
MOZ_ASSERT(child, "No SandboxTestingChild*?");
RunGenericTests(child);
#if defined(XP_WIN)
FileTest("R/W access to shader-cache dir"_ns, NS_APP_USER_PROFILE_50_DIR,
u"shader-cache\\"_ns, FILE_GENERIC_READ | FILE_GENERIC_WRITE, true,
child);
FileTest("R/W access to shader-cache files"_ns, NS_APP_USER_PROFILE_50_DIR,
u"shader-cache\\sandboxTest.txt"_ns,
FILE_GENERIC_READ | FILE_GENERIC_WRITE, true, child);
#else // defined(XP_WIN)
child->ReportNoTests();
#endif // defined(XP_WIN)
}
} // namespace mozilla } // namespace mozilla

View file

@ -142,8 +142,7 @@ void RemoteSandboxBroker::SetSecurityLevelForContentProcess(
"RemoteSandboxBroker::SetSecurityLevelForContentProcess not Implemented"); "RemoteSandboxBroker::SetSecurityLevelForContentProcess not Implemented");
} }
void RemoteSandboxBroker::SetSecurityLevelForGPUProcess( void RemoteSandboxBroker::SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) {
int32_t aSandboxLevel, const nsCOMPtr<nsIFile>& aProfileDir) {
MOZ_CRASH( MOZ_CRASH(
"RemoteSandboxBroker::SetSecurityLevelForGPUProcess not Implemented"); "RemoteSandboxBroker::SetSecurityLevelForGPUProcess not Implemented");
} }

View file

@ -35,8 +35,7 @@ class RemoteSandboxBroker : public AbstractSandboxBroker {
// Security levels for different types of processes // Security levels for different types of processes
void SetSecurityLevelForContentProcess(int32_t aSandboxLevel, void SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
bool aIsFileProcess) override; bool aIsFileProcess) override;
void SetSecurityLevelForGPUProcess( void SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) override;
int32_t aSandboxLevel, const nsCOMPtr<nsIFile>& aProfileDir) override;
bool SetSecurityLevelForRDDProcess() override; bool SetSecurityLevelForRDDProcess() override;
bool SetSecurityLevelForSocketProcess() override; bool SetSecurityLevelForSocketProcess() override;
bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel, bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel,

View file

@ -906,8 +906,7 @@ void SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
} }
} }
void SandboxBroker::SetSecurityLevelForGPUProcess( void SandboxBroker::SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) {
int32_t aSandboxLevel, const nsCOMPtr<nsIFile>& aProfileDir) {
MOZ_RELEASE_ASSERT(mPolicy, "mPolicy must be set before this call."); MOZ_RELEASE_ASSERT(mPolicy, "mPolicy must be set before this call.");
sandbox::JobLevel jobLevel; sandbox::JobLevel jobLevel;
@ -1000,14 +999,14 @@ void SandboxBroker::SetSecurityLevelForGPUProcess(
sandbox::SBOX_ALL_OK == result, sandbox::SBOX_ALL_OK == result,
"With these static arguments AddRule should never fail, what happened?"); "With these static arguments AddRule should never fail, what happened?");
// TEMPORARY WORKAROUND - We don't want to back out the GPU sandbox, so we're // The GPU process needs to write to a shader cache for performance reasons
// going to give access to the entire filesystem until we can figure out a if (sProfileDir) {
// reliable way to only give access to the Shader Cache AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, sProfileDir, u"\\shader-cache"_ns);
sandbox::TargetPolicy::FILES_ALLOW_ANY, L"*");
MOZ_RELEASE_ASSERT( AddCachedDirRule(mPolicy, sandbox::TargetPolicy::FILES_ALLOW_ANY,
sandbox::SBOX_ALL_OK == result, sProfileDir, u"\\shader-cache\\*"_ns);
"With these static arguments AddRule should never fail, what happened?"); }
// The process needs to be able to duplicate shared memory handles, // The process needs to be able to duplicate shared memory handles,
// which are Section handles, to the broker process and other child processes. // which are Section handles, to the broker process and other child processes.

View file

@ -43,8 +43,7 @@ class AbstractSandboxBroker {
virtual void SetSecurityLevelForContentProcess(int32_t aSandboxLevel, virtual void SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
bool aIsFileProcess) = 0; bool aIsFileProcess) = 0;
virtual void SetSecurityLevelForGPUProcess( virtual void SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) = 0;
int32_t aSandboxLevel, const nsCOMPtr<nsIFile>& aProfileDir) = 0;
virtual bool SetSecurityLevelForRDDProcess() = 0; virtual bool SetSecurityLevelForRDDProcess() = 0;
virtual bool SetSecurityLevelForSocketProcess() = 0; virtual bool SetSecurityLevelForSocketProcess() = 0;
virtual bool SetSecurityLevelForUtilityProcess( virtual bool SetSecurityLevelForUtilityProcess(
@ -99,8 +98,7 @@ class SandboxBroker : public AbstractSandboxBroker {
void SetSecurityLevelForContentProcess(int32_t aSandboxLevel, void SetSecurityLevelForContentProcess(int32_t aSandboxLevel,
bool aIsFileProcess) override; bool aIsFileProcess) override;
void SetSecurityLevelForGPUProcess( void SetSecurityLevelForGPUProcess(int32_t aSandboxLevel) override;
int32_t aSandboxLevel, const nsCOMPtr<nsIFile>& aProfileDir) override;
bool SetSecurityLevelForRDDProcess() override; bool SetSecurityLevelForRDDProcess() override;
bool SetSecurityLevelForSocketProcess() override; bool SetSecurityLevelForSocketProcess() override;
bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel, bool SetSecurityLevelForGMPlugin(SandboxLevel aLevel,

View file

@ -5345,6 +5345,16 @@ nsresult XREMain::XRE_mainRun() {
// files can't override JS engine start-up prefs. // files can't override JS engine start-up prefs.
mDirProvider.FinishInitializingUserPrefs(); mDirProvider.FinishInitializingUserPrefs();
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
// Now that we have preferences and the directory provider, we can
// finish initializing SandboxBroker. This must happen before the GFX
// platform is initialized (which will launch the GPU process), which
// occurs when the "app-startup" category is started up below
//
// After this completes, we are ready to launch sandboxed processes
mozilla::SandboxBroker::GeckoDependentInitialize();
#endif
nsCOMPtr<nsIFile> workingDir; nsCOMPtr<nsIFile> workingDir;
rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR, rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR,
getter_AddRefs(workingDir)); getter_AddRefs(workingDir));

View file

@ -161,6 +161,8 @@ nsresult nsXREDirProvider::Initialize(nsIFile* aXULAppDir, nsIFile* aGREDir) {
nsresult nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir) { nsresult nsXREDirProvider::SetProfile(nsIFile* aDir, nsIFile* aLocalDir) {
MOZ_ASSERT(aDir && aLocalDir, "We don't support no-profile apps!"); MOZ_ASSERT(aDir && aLocalDir, "We don't support no-profile apps!");
MOZ_ASSERT(!mProfileDir && !mProfileLocalDir,
"You may only set the profile directories once");
nsresult rv = EnsureDirectoryExists(aDir); nsresult rv = EnsureDirectoryExists(aDir);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
@ -329,15 +331,10 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
nsCOMPtr<nsIFile> file; nsCOMPtr<nsIFile> file;
if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) { if (!strcmp(aProperty, NS_APP_USER_PROFILE_LOCAL_50_DIR)) {
NS_ENSURE_TRUE(mProfileNotified, NS_ERROR_FAILURE);
if (mProfileLocalDir) { if (mProfileLocalDir) {
rv = mProfileLocalDir->Clone(getter_AddRefs(file)); rv = mProfileLocalDir->Clone(getter_AddRefs(file));
} else if (mProfileDir) {
rv = mProfileDir->Clone(getter_AddRefs(file));
} }
} else if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR)) { } else if (!strcmp(aProperty, NS_APP_USER_PROFILE_50_DIR)) {
NS_ENSURE_TRUE(mProfileNotified, NS_ERROR_FAILURE);
if (mProfileDir) { if (mProfileDir) {
rv = mProfileDir->Clone(getter_AddRefs(file)); rv = mProfileDir->Clone(getter_AddRefs(file));
} }
@ -401,8 +398,6 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
} else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) { } else if (!strcmp(aProperty, NS_APP_PROFILE_LOCAL_DIR_STARTUP)) {
if (mProfileLocalDir) { if (mProfileLocalDir) {
rv = mProfileLocalDir->Clone(getter_AddRefs(file)); rv = mProfileLocalDir->Clone(getter_AddRefs(file));
} else if (mProfileDir) {
rv = mProfileDir->Clone(getter_AddRefs(file));
} }
} }
#if defined(XP_UNIX) || defined(XP_MACOSX) #if defined(XP_UNIX) || defined(XP_MACOSX)
@ -714,31 +709,18 @@ nsXREDirProvider::GetFiles(const char* aProperty,
NS_IMETHODIMP NS_IMETHODIMP
nsXREDirProvider::GetDirectory(nsIFile** aResult) { nsXREDirProvider::GetDirectory(nsIFile** aResult) {
NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mProfileDir, NS_ERROR_NOT_INITIALIZED);
return mProfileDir->Clone(aResult); return mProfileDir->Clone(aResult);
} }
void nsXREDirProvider::InitializeUserPrefs() { void nsXREDirProvider::InitializeUserPrefs() {
if (!mPrefsInitialized) { if (!mPrefsInitialized) {
// Temporarily set mProfileNotified to true so that the preference service
// can access the profile directory during initialization. Afterwards, clear
// it so that no other code can inadvertently access it until we get to
// profile-do-change.
mozilla::AutoRestore<bool> ar(mProfileNotified);
mProfileNotified = true;
mozilla::Preferences::InitializeUserPrefs(); mozilla::Preferences::InitializeUserPrefs();
} }
} }
void nsXREDirProvider::FinishInitializingUserPrefs() { void nsXREDirProvider::FinishInitializingUserPrefs() {
if (!mPrefsInitialized) { if (!mPrefsInitialized) {
// See InitializeUserPrefs above.
mozilla::AutoRestore<bool> ar(mProfileNotified);
mProfileNotified = true;
mozilla::Preferences::FinishInitializingUserPrefs(); mozilla::Preferences::FinishInitializingUserPrefs();
mPrefsInitialized = true; mPrefsInitialized = true;
} }
} }
@ -747,12 +729,12 @@ NS_IMETHODIMP
nsXREDirProvider::DoStartup() { nsXREDirProvider::DoStartup() {
nsresult rv; nsresult rv;
if (!mProfileNotified) { if (!mAppStarted) {
nsCOMPtr<nsIObserverService> obsSvc = nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService(); mozilla::services::GetObserverService();
if (!obsSvc) return NS_ERROR_FAILURE; if (!obsSvc) return NS_ERROR_FAILURE;
mProfileNotified = true; mAppStarted = true;
/* /*
Make sure we've setup prefs before profile-do-change to be able to use Make sure we've setup prefs before profile-do-change to be able to use
@ -789,17 +771,6 @@ nsXREDirProvider::DoStartup() {
} }
} }
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
// Call SandboxBroker to initialize things that depend on Gecko machinery
// like the directory provider. We insert this initialization code here
// (rather than in XRE_mainRun) because we need NS_APP_USER_PROFILE_50_DIR
// to be known and so that any child content processes spawned by extensions
// from the notifications below will have all the requisite directories
// white-listed for read/write access. An example of this is the
// tor-launcher launching the network configuration window. See bug 1485836.
mozilla::SandboxBroker::GeckoDependentInitialize();
#endif
#ifdef MOZ_THUNDERBIRD #ifdef MOZ_THUNDERBIRD
bool bgtaskMode = false; bool bgtaskMode = false;
# ifdef MOZ_BACKGROUNDTASKS # ifdef MOZ_BACKGROUNDTASKS
@ -882,7 +853,7 @@ nsXREDirProvider::DoStartup() {
void nsXREDirProvider::DoShutdown() { void nsXREDirProvider::DoShutdown() {
AUTO_PROFILER_LABEL("nsXREDirProvider::DoShutdown", OTHER); AUTO_PROFILER_LABEL("nsXREDirProvider::DoShutdown", OTHER);
if (mProfileNotified) { if (mAppStarted) {
mozilla::AppShutdown::AdvanceShutdownPhase( mozilla::AppShutdown::AdvanceShutdownPhase(
mozilla::ShutdownPhase::AppShutdownNetTeardown, nullptr); mozilla::ShutdownPhase::AppShutdownNetTeardown, nullptr);
mozilla::AppShutdown::AdvanceShutdownPhase( mozilla::AppShutdown::AdvanceShutdownPhase(
@ -901,7 +872,7 @@ void nsXREDirProvider::DoShutdown() {
mozilla::ShutdownPhase::AppShutdownQM, nullptr); mozilla::ShutdownPhase::AppShutdownQM, nullptr);
mozilla::AppShutdown::AdvanceShutdownPhase( mozilla::AppShutdown::AdvanceShutdownPhase(
mozilla::ShutdownPhase::AppShutdownTelemetry, nullptr); mozilla::ShutdownPhase::AppShutdownTelemetry, nullptr);
mProfileNotified = false; mAppStarted = false;
} }
gDataDirProfileLocal = nullptr; gDataDirProfileLocal = nullptr;
@ -1186,12 +1157,13 @@ nsresult nsXREDirProvider::GetProfileStartupDir(nsIFile** aResult) {
} }
nsresult nsXREDirProvider::GetProfileDir(nsIFile** aResult) { nsresult nsXREDirProvider::GetProfileDir(nsIFile** aResult) {
if (mProfileDir) { if (!mProfileDir) {
NS_ENSURE_TRUE(mProfileNotified, NS_ERROR_FAILURE); nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
return mProfileDir->Clone(aResult); getter_AddRefs(mProfileDir));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(mProfileDir, NS_ERROR_FAILURE);
} }
return mProfileDir->Clone(aResult);
return NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, aResult);
} }
NS_IMETHODIMP NS_IMETHODIMP

View file

@ -147,7 +147,7 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
nsCOMPtr<nsIFile> mXULAppDir; nsCOMPtr<nsIFile> mXULAppDir;
nsCOMPtr<nsIFile> mProfileDir; nsCOMPtr<nsIFile> mProfileDir;
nsCOMPtr<nsIFile> mProfileLocalDir; nsCOMPtr<nsIFile> mProfileLocalDir;
bool mProfileNotified = false; bool mAppStarted = false;
bool mPrefsInitialized = false; bool mPrefsInitialized = false;
#if defined(MOZ_SANDBOX) #if defined(MOZ_SANDBOX)
nsCOMPtr<nsIFile> mContentTempDir; nsCOMPtr<nsIFile> mContentTempDir;