Bug 1171796: Add sandbox rule for child process NSPR log file on Windows. r=bbondy

This also moves the initialization of the sandbox TargetServices to earlier in
plugin-container.cpp content_process_main, because it needs to happen before
xul.dll loads.
This commit is contained in:
Bob Owen 2015-07-30 10:04:42 +01:00
parent fbe5e8ab67
commit 77826e3c4a
3 changed files with 74 additions and 29 deletions

View File

@ -154,7 +154,6 @@ content_process_main(int argc, char* argv[])
if (argc < 1) {
return 3;
}
XRE_SetProcessType(argv[--argc]);
bool isNuwa = false;
for (int i = 1; i < argc; i++) {
@ -164,6 +163,26 @@ content_process_main(int argc, char* argv[])
#endif
}
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
if (gIsSandboxEnabled) {
sandbox::TargetServices* target_service =
sandbox::SandboxFactory::GetTargetServices();
if (!target_service) {
return 1;
}
sandbox::ResultCode result = target_service->Init();
if (result != sandbox::SBOX_ALL_OK) {
return 2;
}
mozilla::SandboxTarget::Instance()->SetTargetServices(target_service);
mozilla::sandboxing::PrepareForLogging();
}
#endif
XRE_SetProcessType(argv[--argc]);
#ifdef MOZ_NUWA_PROCESS
if (isNuwa) {
PrepareNuwaProcess();
@ -205,24 +224,6 @@ content_process_main(int argc, char* argv[])
mozilla::SanitizeEnvironmentVariables();
SetDllDirectory(L"");
}
#ifdef MOZ_SANDBOX
if (gIsSandboxEnabled) {
sandbox::TargetServices* target_service =
sandbox::SandboxFactory::GetTargetServices();
if (!target_service) {
return 1;
}
sandbox::ResultCode result =
mozilla::SandboxTarget::Instance()->InitTargetServices(target_service);
if (result != sandbox::SBOX_ALL_OK) {
return 2;
}
mozilla::sandboxing::PrepareForLogging();
}
#endif
#endif
nsAutoPtr<mozilla::gmp::GMPLoader> loader;
#if !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GONK)

View File

@ -554,6 +554,50 @@ AddAppDirToCommandLine(std::vector<std::string>& aCmdLine)
}
}
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
static void
MaybeAddNsprLogFileAccess(std::vector<std::wstring>& aAllowedFilesReadWrite)
{
const char* nsprLogFileEnv = PR_GetEnv("NSPR_LOG_FILE");
if (!nsprLogFileEnv) {
return;
}
nsCOMPtr<nsIFile> file;
nsresult rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR,
getter_AddRefs(file));
if (NS_FAILED(rv) || !file) {
NS_WARNING("Failed to get current working directory");
return;
}
nsDependentCString nsprLogFile(nsprLogFileEnv);
rv = file->AppendRelativeNativePath(nsprLogFile);
if (NS_FAILED(rv)) {
// Not a relative path, try it as an absolute one.
rv = file->InitWithNativePath(nsprLogFile);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
}
nsAutoString resolvedFilePath;
rv = file->GetPath(resolvedFilePath);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
// Update the environment variable as well as adding the rule, because the
// Chromium sandbox can only allow access to fully qualified file paths. This
// only affects the environment for the child process we're about to create,
// because this will get reset to the original value in PerformAsyncLaunch.
aAllowedFilesReadWrite.push_back(resolvedFilePath.get());
nsAutoCString resolvedEnvVar("NSPR_LOG_FILE=");
AppendUTF16toUTF8(resolvedFilePath, resolvedEnvVar);
PR_SetEnv(resolvedEnvVar.get());
}
#endif
bool
GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExtraOpts, base::ProcessArchitecture arch)
{
@ -891,6 +935,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
};
if (shouldSandboxCurrentProcess) {
MaybeAddNsprLogFileAccess(mAllowedFilesReadWrite);
for (auto it = mAllowedFilesRead.begin();
it != mAllowedFilesRead.end();
++it) {

View File

@ -11,6 +11,7 @@
#include "base/MissingBasicTypes.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/target_services.h"
#ifdef TARGET_SANDBOX_EXPORTS
#define TARGET_SANDBOX_EXPORT __declspec(dllexport)
@ -35,22 +36,20 @@ public:
/**
* Used by the application to pass in the target services that provide certain
* functions to the sandboxed code.
* The target services must already be initialized.
*
* @param aTargetServices The target services that will be initialized and used
* @param aTargetServices The target services that will be used
*/
sandbox::ResultCode
InitTargetServices(sandbox::TargetServices* aTargetServices)
void SetTargetServices(sandbox::TargetServices* aTargetServices)
{
MOZ_ASSERT(aTargetServices);
MOZ_ASSERT(!mTargetServices,
"Sandbox TargetServices must only be initialized once.");
"Sandbox TargetServices must only be set once.");
// We use process_state_ instead of InitCalled() here due to linking issues.
MOZ_ASSERT(aTargetServices->GetState()->process_state_ > 1,
"Sandbox TargetServices must already be initialized.");
sandbox::ResultCode result = aTargetServices->Init();
if (sandbox::SBOX_ALL_OK == result) {
mTargetServices = aTargetServices;
}
return result;
mTargetServices = aTargetServices;
}
/**