forked from mirrors/gecko-dev
Bug 1704500: Use structs to normalize utility process sandbox code r=gerard-majax,bobowen
Adds UtilitySandboxProps, which abstract the more universal sandbox properties into a data object so that the various types of utility process can simply list them. This also adds a somewhat weak sandbox for the new "WindowsUtils" utility process type. Depends on D155018 Differential Revision: https://phabricator.services.mozilla.com/D155019
This commit is contained in:
parent
2e959c2130
commit
02ce7177c5
1 changed files with 188 additions and 128 deletions
|
|
@ -65,6 +65,7 @@ static LazyLogModule sSandboxBrokerLog("SandboxBroker");
|
|||
|
||||
#define LOG_E(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Error, (__VA_ARGS__))
|
||||
#define LOG_W(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Warning, (__VA_ARGS__))
|
||||
#define LOG_D(...) MOZ_LOG(sSandboxBrokerLog, LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
// Used to store whether we have accumulated an error combination for this
|
||||
// session.
|
||||
|
|
@ -1257,174 +1258,233 @@ bool SandboxBroker::SetSecurityLevelForSocketProcess() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SandboxBroker::SetSecurityLevelForUtilityProcess(
|
||||
mozilla::ipc::SandboxingKind aSandbox) {
|
||||
if (!mPolicy) {
|
||||
return false;
|
||||
}
|
||||
// A strict base sandbox for utility sandboxes to adapt.
|
||||
struct UtilitySandboxProps {
|
||||
sandbox::JobLevel mJobLevel = sandbox::JOB_LOCKDOWN;
|
||||
|
||||
auto jobLevel = sandbox::JOB_LOCKDOWN;
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
|
||||
jobLevel = sandbox::JOB_INTERACTIVE;
|
||||
}
|
||||
#endif
|
||||
auto result = SetJobLevel(mPolicy, jobLevel, 0 /* ui_exceptions */);
|
||||
SANDBOX_ENSURE_SUCCESS(
|
||||
result,
|
||||
"SetJobLevel should never fail with these arguments, what happened?");
|
||||
sandbox::TokenLevel mInitialTokenLevel = sandbox::USER_RESTRICTED_SAME_ACCESS;
|
||||
sandbox::TokenLevel mDelayedTokenLevel = sandbox::USER_LOCKDOWN;
|
||||
|
||||
auto lockdownLevel = sandbox::USER_LOCKDOWN;
|
||||
if (aSandbox == mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF) {
|
||||
lockdownLevel = sandbox::USER_LIMITED;
|
||||
}
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
|
||||
lockdownLevel = sandbox::USER_RESTRICTED_NON_ADMIN;
|
||||
}
|
||||
#endif
|
||||
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
||||
lockdownLevel);
|
||||
SANDBOX_ENSURE_SUCCESS(
|
||||
result,
|
||||
"SetTokenLevel should never fail with these arguments, what happened?");
|
||||
sandbox::IntegrityLevel mInitialIntegrityLevel = // before lockdown
|
||||
sandbox::INTEGRITY_LEVEL_LOW;
|
||||
sandbox::IntegrityLevel mDelayedIntegrityLevel = // after lockdown
|
||||
sandbox::INTEGRITY_LEVEL_UNTRUSTED;
|
||||
|
||||
bool useAlternateWindowStation = true;
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
|
||||
useAlternateWindowStation = false;
|
||||
}
|
||||
#endif
|
||||
result = mPolicy->SetAlternateDesktop(useAlternateWindowStation);
|
||||
if (NS_WARN_IF(result != sandbox::SBOX_ALL_OK)) {
|
||||
LOG_W("SetAlternateDesktop failed, result: %i, last error: %lx", result,
|
||||
::GetLastError());
|
||||
}
|
||||
bool mUseAlternateWindowStation = true;
|
||||
bool mUseWin32kLockdown = true;
|
||||
bool mUseCig = true;
|
||||
|
||||
result = mPolicy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"SetIntegrityLevel should never fail with these "
|
||||
"arguments, what happened?");
|
||||
|
||||
auto integrityLevel = sandbox::INTEGRITY_LEVEL_UNTRUSTED;
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
if (aSandbox == mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM) {
|
||||
integrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
}
|
||||
#endif
|
||||
result = mPolicy->SetDelayedIntegrityLevel(integrityLevel);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"SetDelayedIntegrityLevel should never fail with "
|
||||
"these arguments, what happened?");
|
||||
|
||||
mPolicy->SetLockdownDefaultDacl();
|
||||
mPolicy->AddRestrictingRandomSid();
|
||||
|
||||
sandbox::MitigationFlags mitigations =
|
||||
sandbox::MitigationFlags mInitialMitigations =
|
||||
sandbox::MITIGATION_BOTTOM_UP_ASLR | sandbox::MITIGATION_HEAP_TERMINATE |
|
||||
sandbox::MITIGATION_SEHOP | sandbox::MITIGATION_EXTENSION_POINT_DISABLE |
|
||||
sandbox::MITIGATION_DEP_NO_ATL_THUNK | sandbox::MITIGATION_DEP |
|
||||
sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32 |
|
||||
sandbox::MITIGATION_CET_COMPAT_MODE;
|
||||
|
||||
const Maybe<Vector<const wchar_t*>>& exceptionModules =
|
||||
GetPrespawnCigExceptionModules();
|
||||
if (exceptionModules.isSome()) {
|
||||
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
sandbox::MitigationFlags mDelayedMitigations =
|
||||
sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER |
|
||||
sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
|
||||
};
|
||||
|
||||
struct GenericUtilitySandboxProps : public UtilitySandboxProps {};
|
||||
|
||||
struct UtilityAudioDecodingWmfSandboxProps : public UtilitySandboxProps {
|
||||
UtilityAudioDecodingWmfSandboxProps() {
|
||||
mDelayedTokenLevel = sandbox::USER_LIMITED;
|
||||
mDelayedMitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER;
|
||||
#ifdef MOZ_WMF
|
||||
if (StaticPrefs::security_sandbox_utility_wmf_acg_enabled()) {
|
||||
mDelayedMitigations |= DynamicCodeFlagForSystemMediaLibraries();
|
||||
}
|
||||
#else
|
||||
mDelayedMitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
|
||||
#endif // MOZ_WMF
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
struct UtilityMfMediaEngineCdmSandboxProps : public UtilitySandboxProps {
|
||||
UtilityMfMediaEngineCdmSandboxProps() {
|
||||
mJobLevel = sandbox::JOB_INTERACTIVE;
|
||||
mDelayedTokenLevel = sandbox::USER_RESTRICTED_NON_ADMIN;
|
||||
mUseAlternateWindowStation = false;
|
||||
mDelayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
mUseWin32kLockdown = false;
|
||||
mDelayedMitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
struct WindowsUtilitySandboxProps : public UtilitySandboxProps {
|
||||
WindowsUtilitySandboxProps() {
|
||||
mJobLevel = sandbox::JOB_INTERACTIVE;
|
||||
mDelayedTokenLevel = sandbox::USER_RESTRICTED_SAME_ACCESS;
|
||||
mUseAlternateWindowStation = false;
|
||||
mInitialIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
|
||||
mDelayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
|
||||
mUseWin32kLockdown = false;
|
||||
mUseCig = false;
|
||||
mDelayedMitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER;
|
||||
}
|
||||
};
|
||||
|
||||
void LogUtilitySandboxProps(const UtilitySandboxProps& us) {
|
||||
if (!static_cast<LogModule*>(sSandboxBrokerLog)->ShouldLog(LogLevel::Debug)) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = mPolicy->SetProcessMitigations(mitigations);
|
||||
nsAutoCString logMsg;
|
||||
logMsg.AppendPrintf("Building sandbox for utility process:\n");
|
||||
logMsg.AppendPrintf("\tJob Level: %d\n", static_cast<int>(us.mJobLevel));
|
||||
logMsg.AppendPrintf("\tInitial Token Level: %d\n",
|
||||
static_cast<int>(us.mInitialTokenLevel));
|
||||
logMsg.AppendPrintf("\tDelayed Token Level: %d\n",
|
||||
static_cast<int>(us.mDelayedTokenLevel));
|
||||
logMsg.AppendPrintf("\tInitial Integrity Level: %d\n",
|
||||
static_cast<int>(us.mInitialIntegrityLevel));
|
||||
logMsg.AppendPrintf("\tDelayed Integrity Level: %d\n",
|
||||
static_cast<int>(us.mDelayedIntegrityLevel));
|
||||
logMsg.AppendPrintf("\tUse Alternate Window Station: %s\n",
|
||||
us.mUseAlternateWindowStation ? "yes" : "no");
|
||||
logMsg.AppendPrintf("\tUse Win32k Lockdown: %s\n",
|
||||
us.mUseWin32kLockdown ? "yes" : "no");
|
||||
logMsg.AppendPrintf("\tUse CIG: %s\n", us.mUseCig ? "yes" : "no");
|
||||
logMsg.AppendPrintf("\tInitial mitigations: %016llx\n",
|
||||
static_cast<uint64_t>(us.mInitialMitigations));
|
||||
logMsg.AppendPrintf("\tDelayed mitigations: %016llx\n",
|
||||
static_cast<uint64_t>(us.mDelayedMitigations));
|
||||
|
||||
LOG_D("%s", logMsg.get());
|
||||
}
|
||||
|
||||
bool BuildUtilitySandbox(sandbox::TargetPolicy* policy,
|
||||
const UtilitySandboxProps& us) {
|
||||
LogUtilitySandboxProps(us);
|
||||
|
||||
auto result = SetJobLevel(policy, us.mJobLevel, 0 /* ui_exceptions */);
|
||||
SANDBOX_ENSURE_SUCCESS(
|
||||
result,
|
||||
"SetJobLevel should never fail with these arguments, what happened?");
|
||||
|
||||
result = policy->SetTokenLevel(us.mInitialTokenLevel, us.mDelayedTokenLevel);
|
||||
SANDBOX_ENSURE_SUCCESS(
|
||||
result,
|
||||
"SetTokenLevel should never fail with these arguments, what happened?");
|
||||
|
||||
result = policy->SetAlternateDesktop(us.mUseAlternateWindowStation);
|
||||
if (NS_WARN_IF(result != sandbox::SBOX_ALL_OK)) {
|
||||
LOG_W("SetAlternateDesktop failed, result: %i, last error: %lx", result,
|
||||
::GetLastError());
|
||||
}
|
||||
|
||||
result = policy->SetIntegrityLevel(us.mInitialIntegrityLevel);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"SetIntegrityLevel should never fail with these "
|
||||
"arguments, what happened?");
|
||||
|
||||
result = policy->SetDelayedIntegrityLevel(us.mDelayedIntegrityLevel);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"SetDelayedIntegrityLevel should never fail with "
|
||||
"these arguments, what happened?");
|
||||
|
||||
policy->SetLockdownDefaultDacl();
|
||||
policy->AddRestrictingRandomSid();
|
||||
|
||||
sandbox::MitigationFlags initialMitigations = us.mInitialMitigations;
|
||||
sandbox::MitigationFlags delayedMitigations = us.mDelayedMitigations;
|
||||
|
||||
if (us.mUseCig) {
|
||||
const Maybe<Vector<const wchar_t*>>& exceptionModules =
|
||||
GetPrespawnCigExceptionModules();
|
||||
if (exceptionModules.isSome()) {
|
||||
initialMitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
} else {
|
||||
delayedMitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
}
|
||||
}
|
||||
|
||||
result = policy->SetProcessMitigations(initialMitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Invalid flags for SetProcessMitigations.");
|
||||
|
||||
if (exceptionModules.isSome()) {
|
||||
// This needs to be called after MITIGATION_FORCE_MS_SIGNED_BINS is set
|
||||
// because of DCHECK in PolicyBase::AddRuleInternal.
|
||||
result = InitSignedPolicyRulesToBypassCig(mPolicy, exceptionModules.ref());
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Failed to initialize signed policy rules.");
|
||||
}
|
||||
|
||||
// Win32k lockdown might not work on earlier versions
|
||||
// Bug 1719212, 1769992
|
||||
if (IsWin10FallCreatorsUpdateOrLater()
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
&& aSandbox != mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM
|
||||
#endif
|
||||
) {
|
||||
result = AddWin32kLockdownPolicy(mPolicy, false);
|
||||
if (IsWin10FallCreatorsUpdateOrLater() && us.mUseWin32kLockdown) {
|
||||
result = AddWin32kLockdownPolicy(policy, false);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Failed to add the win32k lockdown policy");
|
||||
}
|
||||
|
||||
mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER;
|
||||
if (us.mUseCig) {
|
||||
const Maybe<Vector<const wchar_t*>>& exceptionModules =
|
||||
GetPrespawnCigExceptionModules();
|
||||
if (exceptionModules.isSome()) {
|
||||
// This needs to be called after MITIGATION_FORCE_MS_SIGNED_BINS is set
|
||||
// because of DCHECK in PolicyBase::AddRuleInternal.
|
||||
result = InitSignedPolicyRulesToBypassCig(policy, exceptionModules.ref());
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"Failed to initialize signed policy rules.");
|
||||
}
|
||||
|
||||
switch (aSandbox) {
|
||||
#ifdef MOZ_WMF
|
||||
// The audio decoder process depends on MsAudDecMFT.dll.
|
||||
case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
|
||||
if (StaticPrefs::security_sandbox_utility_wmf_acg_enabled()) {
|
||||
mitigations |= DynamicCodeFlagForSystemMediaLibraries();
|
||||
}
|
||||
break;
|
||||
#endif // MOZ_WMF
|
||||
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
// No ACG on CDM utility processes.
|
||||
case mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM:
|
||||
break;
|
||||
#endif // MOZ_WMF_MEDIA_ENGINE
|
||||
|
||||
default:
|
||||
mitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
|
||||
// Running audio decoder somehow fails on MSIX packages unless we do that
|
||||
if (mozilla::HasPackageIdentity() && exceptionModules.isNothing()) {
|
||||
const Vector<const wchar_t*> emptyVector;
|
||||
result = InitSignedPolicyRulesToBypassCig(policy, emptyVector);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"Failed to initialize signed policy rules.");
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptionModules.isNothing()) {
|
||||
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
}
|
||||
|
||||
result = mPolicy->SetDelayedProcessMitigations(mitigations);
|
||||
result = policy->SetDelayedProcessMitigations(delayedMitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"Invalid flags for SetDelayedProcessMitigations.");
|
||||
|
||||
// Running audio decoder somehow fails on MSIX packages unless we do that
|
||||
if (mozilla::HasPackageIdentity() && exceptionModules.isNothing()) {
|
||||
const Vector<const wchar_t*> emptyVector;
|
||||
result = InitSignedPolicyRulesToBypassCig(mPolicy, emptyVector);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Failed to initialize signed policy rules.");
|
||||
}
|
||||
|
||||
// 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
|
||||
// "chrome." so the sandboxed process cannot connect to system services.
|
||||
result = mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
||||
sandbox::TargetPolicy::FILES_ALLOW_ANY,
|
||||
L"\\??\\pipe\\chrome.*");
|
||||
result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
||||
sandbox::TargetPolicy::FILES_ALLOW_ANY,
|
||||
L"\\??\\pipe\\chrome.*");
|
||||
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.*");
|
||||
result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
||||
sandbox::TargetPolicy::FILES_ALLOW_ANY,
|
||||
L"\\??\\pipe\\gecko-crash-server-pipe.*");
|
||||
SANDBOX_ENSURE_SUCCESS(
|
||||
result,
|
||||
"With these static arguments AddRule should never fail, what happened?");
|
||||
|
||||
switch (aSandbox) {
|
||||
case mozilla::ipc::SandboxingKind::GENERIC_UTILITY:
|
||||
case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
|
||||
#if MOZ_WMF_MEDIA_ENGINE
|
||||
case mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM:
|
||||
#endif
|
||||
// Nothing specific to perform yet?
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
MOZ_ASSERT(false, "Invalid SandboxingKind");
|
||||
break;
|
||||
bool SandboxBroker::SetSecurityLevelForUtilityProcess(
|
||||
mozilla::ipc::SandboxingKind aSandbox) {
|
||||
if (!mPolicy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
switch (aSandbox) {
|
||||
case mozilla::ipc::SandboxingKind::GENERIC_UTILITY:
|
||||
return BuildUtilitySandbox(mPolicy, GenericUtilitySandboxProps());
|
||||
case mozilla::ipc::SandboxingKind::UTILITY_AUDIO_DECODING_WMF:
|
||||
return BuildUtilitySandbox(mPolicy,
|
||||
UtilityAudioDecodingWmfSandboxProps());
|
||||
#ifdef MOZ_WMF_MEDIA_ENGINE
|
||||
case mozilla::ipc::SandboxingKind::MF_MEDIA_ENGINE_CDM:
|
||||
return BuildUtilitySandbox(mPolicy,
|
||||
UtilityMfMediaEngineCdmSandboxProps());
|
||||
#endif
|
||||
case mozilla::ipc::SandboxingKind::WINDOWS_UTILS:
|
||||
return BuildUtilitySandbox(mPolicy, WindowsUtilitySandboxProps());
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown sandboxing value");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SandboxBroker::SetSecurityLevelForGMPlugin(SandboxLevel aLevel,
|
||||
|
|
|
|||
Loading…
Reference in a new issue