Bug 1146873 - Handling sandbox policy setup failures. r=bobowen

This commit is contained in:
Gabor Krizsanits 2016-06-06 15:13:33 +02:00
Родитель 3a01463f29
Коммит 6c0e1dc69f
3 изменённых файлов: 113 добавлений и 82 удалений

Просмотреть файл

@ -583,15 +583,19 @@ GeckoChildProcessHost::RunPerformAsyncLaunch(std::vector<std::string> aExtraOpts
{
InitializeChannel();
if (PerformAsyncLaunch(aExtraOpts, aArch)) {
return true;
} else {
bool ok = PerformAsyncLaunch(aExtraOpts, aArch);
if (!ok) {
// WaitUntilConnected might be waiting for us to signal.
// If something failed let's set the error state and notify.
MonitorAutoLock lock(mMonitor);
mProcessState = PROCESS_ERROR;
lock.Notify();
CHROMIUM_LOG(ERROR) << "Failed to launch " <<
XRE_ChildProcessTypeToString(mProcessType) << " subprocess";
Telemetry::Accumulate(Telemetry::SUBPROCESS_LAUNCH_FAILURE,
nsDependentCString(XRE_ChildProcessTypeToString(mProcessType)));
return false;
}
return ok;
}
void
@ -1030,6 +1034,9 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
#if defined(MOZ_CONTENT_SANDBOX)
if (mSandboxLevel > 0 &&
!PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
// For now we treat every failure as fatal in SetSecurityLevelForContentProcess
// and just crash there right away. Should this change in the future then we
// should also handle the error here.
mSandboxBroker.SetSecurityLevelForContentProcess(mSandboxLevel);
cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
shouldSandboxCurrentProcess = true;
@ -1040,16 +1047,16 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
case GeckoProcessType_Plugin:
if (mSandboxLevel > 0 &&
!PR_GetEnv("MOZ_DISABLE_NPAPI_SANDBOX")) {
mSandboxBroker.SetSecurityLevelForPluginProcess(mSandboxLevel);
bool ok = mSandboxBroker.SetSecurityLevelForPluginProcess(mSandboxLevel);
if (!ok) {
return false;
}
cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
shouldSandboxCurrentProcess = true;
}
break;
case GeckoProcessType_IPDLUnitTest:
// XXX: We don't sandbox this process type yet
// mSandboxBroker.SetSecurityLevelForIPDLUnitTestProcess();
// cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
// shouldSandboxCurrentProcess = true;
break;
case GeckoProcessType_GMPlugin:
if (!PR_GetEnv("MOZ_DISABLE_GMP_SANDBOX")) {
@ -1060,7 +1067,10 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
bool isWidevine = std::any_of(aExtraOpts.begin(), aExtraOpts.end(),
[](const std::string arg) { return arg.find("gmp-widevinecdm") != std::string::npos; });
auto level = isWidevine ? SandboxBroker::Restricted : SandboxBroker::LockDown;
mSandboxBroker.SetSecurityLevelForGMPlugin(level);
bool ok = mSandboxBroker.SetSecurityLevelForGMPlugin(level);
if (!ok) {
return false;
}
cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
shouldSandboxCurrentProcess = true;
}
@ -1146,9 +1156,6 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
#endif
if (!process) {
MonitorAutoLock lock(mMonitor);
mProcessState = PROCESS_ERROR;
lock.Notify();
return false;
}
// NB: on OS X, we block much longer than we need to in order to

Просмотреть файл

@ -86,12 +86,10 @@ SandboxBroker::LaunchApp(const wchar_t *aPath,
}
#if defined(MOZ_CONTENT_SANDBOX)
bool
void
SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel)
{
if (!mPolicy) {
return false;
}
MOZ_RELEASE_ASSERT(mPolicy, "mPolicy must be set before this call.");
sandbox::JobLevel jobLevel;
sandbox::TokenLevel accessTokenLevel;
@ -101,6 +99,7 @@ SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel)
// The setting of these levels is pretty arbitrary, but they are a useful (if
// crude) tool while we are tightening the policy. Gaps are left to try and
// avoid changing their meaning.
MOZ_RELEASE_ASSERT(aSandboxLevel >= 1, "Should not be called with aSandboxLevel < 1");
if (aSandboxLevel >= 20) {
jobLevel = sandbox::JOB_LOCKDOWN;
accessTokenLevel = sandbox::USER_LOCKDOWN;
@ -121,27 +120,29 @@ SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel)
accessTokenLevel = sandbox::USER_NON_ADMIN;
initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
} else {
MOZ_ASSERT_UNREACHABLE("Should not be called with aSandboxLevel < 1");
return false;
}
sandbox::ResultCode result = mPolicy->SetJobLevel(jobLevel,
sandbox::ResultCode result = mPolicy->SetJobLevel(jobLevel,
0 /* ui_exceptions */);
bool ret = (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"Setting job level failed, have you set memory limit when jobLevel == JOB_NONE?");
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
accessTokenLevel);
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"Lockdown level cannot be USER_UNPROTECTED or USER_LAST if initial level was USER_RESTRICTED_SAME_ACCESS");
result = mPolicy->SetIntegrityLevel(initialIntegrityLevel);
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"SetIntegrityLevel should never fail, what happened?");
result = mPolicy->SetDelayedIntegrityLevel(delayedIntegrityLevel);
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"SetDelayedIntegrityLevel should never fail, what happened?");
if (aSandboxLevel > 2) {
result = mPolicy->SetAlternateDesktop(true);
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"Failed to create alternate desktop for sandbox.");
}
sandbox::MitigationFlags mitigations =
@ -152,14 +153,16 @@ SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel)
sandbox::MITIGATION_DEP;
result = mPolicy->SetProcessMitigations(mitigations);
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"Invalid flags for SetProcessMitigations.");
mitigations =
sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER;
result = mPolicy->SetDelayedProcessMitigations(mitigations);
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"Invalid flags for SetDelayedProcessMitigations.");
// Add the policy for the client side of a pipe. It is just a file
// in the \pipe\ namespace. We restrict it to pipes that start with
@ -167,32 +170,41 @@ SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel)
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\chrome.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"With these static arguments AddRule should never fail, what happened?");
// Add the policy for the client side of the crash server pipe.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"With these static arguments AddRule should never fail, what happened?");
// The content process needs to be able to duplicate named pipes back to the
// broker process, which are File type handles.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
sandbox::TargetPolicy::HANDLES_DUP_BROKER,
L"File");
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"With these static arguments AddRule should never fail, what happened?");
// The content process needs to be able to duplicate shared memory to the
// broker process, which are Section type handles.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
sandbox::TargetPolicy::HANDLES_DUP_BROKER,
L"Section");
ret = ret && (sandbox::SBOX_ALL_OK == result);
return ret;
MOZ_RELEASE_ASSERT(sandbox::SBOX_ALL_OK == result,
"With these static arguments AddRule should never fail, what happened?");
}
#endif
#define SANDBOX_ENSURE_SUCCESS(result, message) \
do { \
MOZ_ASSERT(sandbox::SBOX_ALL_OK == result, message); \
if (sandbox::SBOX_ALL_OK != result) \
return false; \
} while (0)
bool
SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel)
{
@ -224,16 +236,21 @@ SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel)
sandbox::ResultCode result = mPolicy->SetJobLevel(jobLevel,
0 /* ui_exceptions */);
bool ret = (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"Setting job level failed, have you set memory limit when jobLevel == JOB_NONE?");
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
accessTokenLevel);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"Lockdown level cannot be USER_UNPROTECTED or USER_LAST if initial level was USER_RESTRICTED_SAME_ACCESS");
result = mPolicy->SetIntegrityLevel(initialIntegrityLevel);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"SetIntegrityLevel should never fail, what happened?");
result = mPolicy->SetDelayedIntegrityLevel(delayedIntegrityLevel);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"SetDelayedIntegrityLevel should never fail, what happened?");
sandbox::MitigationFlags mitigations =
sandbox::MITIGATION_BOTTOM_UP_ASLR |
@ -243,7 +260,8 @@ SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel)
sandbox::MITIGATION_DEP;
result = mPolicy->SetProcessMitigations(mitigations);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"Invalid flags for SetProcessMitigations.");
// Add the policy for the client side of a pipe. It is just a file
// in the \pipe\ namespace. We restrict it to pipes that start with
@ -251,13 +269,15 @@ SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel)
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\chrome.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
// Add the policy for the client side of the crash server pipe.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
// The NPAPI process needs to be able to duplicate shared memory to the
// content process and broker process, which are Section type handles.
@ -265,36 +285,23 @@ SandboxBroker::SetSecurityLevelForPluginProcess(int32_t aSandboxLevel)
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
sandbox::TargetPolicy::HANDLES_DUP_ANY,
L"Section");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_HANDLES,
sandbox::TargetPolicy::HANDLES_DUP_BROKER,
L"Section");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
// The following is required for the Java plugin.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\jpi2_pid*_pipe*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
return ret;
}
bool
SandboxBroker::SetSecurityLevelForIPDLUnitTestProcess()
{
if (!mPolicy) {
return false;
}
auto result = mPolicy->SetJobLevel(sandbox::JOB_NONE, 0);
bool ret = (sandbox::SBOX_ALL_OK == result);
result =
mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
sandbox::USER_RESTRICTED_SAME_ACCESS);
ret = ret && (sandbox::SBOX_ALL_OK == result);
return ret;
return true;
}
bool
@ -305,22 +312,26 @@ SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel)
}
auto result = mPolicy->SetJobLevel(sandbox::JOB_LOCKDOWN, 0);
bool ret = (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"SetJobLevel should never fail with these arguments, what happened?");
auto level = (aLevel == Restricted) ?
sandbox::USER_RESTRICTED : sandbox::USER_LOCKDOWN;
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS, level);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"SetTokenLevel should never fail with these arguments, what happened?");
result = mPolicy->SetAlternateDesktop(true);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"Failed to create alternate desktop for sandbox.");
result = mPolicy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
ret = ret && (sandbox::SBOX_ALL_OK == result);
MOZ_ASSERT(sandbox::SBOX_ALL_OK == result,
"SetIntegrityLevel should never fail with these arguments, what happened?");
result =
mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"SetIntegrityLevel should never fail with these arguments, what happened?");
sandbox::MitigationFlags mitigations =
sandbox::MITIGATION_BOTTOM_UP_ASLR |
@ -330,14 +341,16 @@ SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel)
sandbox::MITIGATION_DEP;
result = mPolicy->SetProcessMitigations(mitigations);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"Invalid flags for SetProcessMitigations.");
mitigations =
sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER;
result = mPolicy->SetDelayedProcessMitigations(mitigations);
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"Invalid flags for SetDelayedProcessMitigations.");
// Add the policy for the client side of a pipe. It is just a file
// in the \pipe\ namespace. We restrict it to pipes that start with
@ -345,13 +358,15 @@ SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel)
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\chrome.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
// Add the policy for the client side of the crash server pipe.
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
sandbox::TargetPolicy::FILES_ALLOW_ANY,
L"\\??\\pipe\\gecko-crash-server-pipe.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
#ifdef DEBUG
// The plugin process can't create named events, but we'll
@ -360,7 +375,8 @@ SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel)
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SYNC,
sandbox::TargetPolicy::EVENTS_ALLOW_ANY,
L"ChromeIPCLog.*");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
#endif
// The following rules were added because, during analysis of an EME
@ -371,22 +387,26 @@ SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel)
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_CURRENT_USER");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_CURRENT_USER\\Control Panel\\Desktop");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_CURRENT_USER\\Control Panel\\Desktop\\LanguageConfiguration");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SideBySide");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
// The following rules were added because, during analysis of an EME
@ -397,25 +417,30 @@ SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel)
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Microsoft\\MUI\\Settings");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_CURRENT_USER\\Software\\Policies\\Microsoft\\Control Panel\\Desktop");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_CURRENT_USER\\Control Panel\\Desktop\\PreferredUILanguages");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_REGISTRY,
sandbox::TargetPolicy::REG_ALLOW_READONLY,
L"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SideBySide\\PreferExternalManifest");
ret = ret && (sandbox::SBOX_ALL_OK == result);
SANDBOX_ENSURE_SUCCESS(result,
"With these static arguments AddRule should never fail, what happened?");
return ret;
return true;
}
#undef SANDBOX_ENSURE_SUCCESS
bool
SandboxBroker::AllowReadFile(wchar_t const *file)

Просмотреть файл

@ -32,10 +32,9 @@ public:
// Security levels for different types of processes
#if defined(MOZ_CONTENT_SANDBOX)
bool SetSecurityLevelForContentProcess(int32_t aSandboxLevel);
void SetSecurityLevelForContentProcess(int32_t aSandboxLevel);
#endif
bool SetSecurityLevelForPluginProcess(int32_t aSandboxLevel);
bool SetSecurityLevelForIPDLUnitTestProcess();
enum SandboxLevel {
LockDown,
Restricted