mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 1820535: Refactor CIG sandbox policy set up. r=handyman
This moves the configuration into a separate function to simplify the main policy settings functions and ensure that mitigations and policy rules are set in the correct order. Differential Revision: https://phabricator.services.mozilla.com/D171759
This commit is contained in:
parent
91152cebf4
commit
f5b2ded59f
@ -27,7 +27,6 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "mozilla/WinDllServices.h"
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
@ -82,6 +81,8 @@ static sandbox::ResultCode AddWin32kLockdownPolicy(
|
||||
}
|
||||
|
||||
sandbox::MitigationFlags flags = aPolicy->GetProcessMitigations();
|
||||
MOZ_ASSERT(flags,
|
||||
"Mitigations should be set before AddWin32kLockdownPolicy.");
|
||||
MOZ_ASSERT(!(flags & sandbox::MITIGATION_WIN32K_DISABLE),
|
||||
"Check not enabling twice. Should not happen.");
|
||||
|
||||
@ -466,50 +467,59 @@ static const Maybe<Vector<const wchar_t*>>& GetPrespawnCigExceptionModules() {
|
||||
#endif
|
||||
}
|
||||
|
||||
static sandbox::ResultCode InitSignedPolicyRulesToBypassCig(
|
||||
sandbox::TargetPolicy* aPolicy,
|
||||
const Vector<const wchar_t*>& aExceptionModules) {
|
||||
static UniquePtr<nsString> sInstallDir;
|
||||
if (!sInstallDir) {
|
||||
// Since this function is 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(
|
||||
TaskCategory::Other,
|
||||
NS_NewRunnableFunction("InitSignedPolicyRulesToBypassCig",
|
||||
std::move(setClearOnShutdown)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!sInstallDir) {
|
||||
return sandbox::SBOX_ERROR_GENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
static sandbox::ResultCode AllowProxyLoadFromBinDir(
|
||||
sandbox::TargetPolicy* aPolicy) {
|
||||
// Allow modules in the directory containing the executable such as
|
||||
// mozglue.dll, nss3.dll, etc.
|
||||
auto result = aPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
|
||||
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD,
|
||||
sInstallDir->get());
|
||||
nsAutoString rulePath(sBinDir->get());
|
||||
rulePath.Append(u"\\*"_ns);
|
||||
return aPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
|
||||
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD,
|
||||
rulePath.get());
|
||||
}
|
||||
|
||||
static sandbox::ResultCode AddCigToPolicy(
|
||||
sandbox::TargetPolicy* aPolicy, bool aAlwaysProxyBinDirLoading = false) {
|
||||
const Maybe<Vector<const wchar_t*>>& exceptionModules =
|
||||
GetPrespawnCigExceptionModules();
|
||||
if (exceptionModules.isNothing()) {
|
||||
sandbox::MitigationFlags delayedMitigations =
|
||||
aPolicy->GetDelayedProcessMitigations();
|
||||
MOZ_ASSERT(delayedMitigations,
|
||||
"Delayed mitigations should be set before AddCigToPolicy.");
|
||||
MOZ_ASSERT(!(delayedMitigations & sandbox::MITIGATION_FORCE_MS_SIGNED_BINS),
|
||||
"AddCigToPolicy should not be called twice.");
|
||||
|
||||
delayedMitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
sandbox::ResultCode result =
|
||||
aPolicy->SetDelayedProcessMitigations(delayedMitigations);
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aAlwaysProxyBinDirLoading) {
|
||||
result = AllowProxyLoadFromBinDir(aPolicy);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
sandbox::MitigationFlags mitigations = aPolicy->GetProcessMitigations();
|
||||
MOZ_ASSERT(mitigations, "Mitigations should be set before AddCigToPolicy.");
|
||||
MOZ_ASSERT(!(mitigations & sandbox::MITIGATION_FORCE_MS_SIGNED_BINS),
|
||||
"AddCigToPolicy should not be called twice.");
|
||||
|
||||
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
sandbox::ResultCode result = aPolicy->SetProcessMitigations(mitigations);
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aExceptionModules.empty()) {
|
||||
return sandbox::SBOX_ALL_OK;
|
||||
result = AllowProxyLoadFromBinDir(aPolicy);
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (const wchar_t* path : aExceptionModules) {
|
||||
for (const wchar_t* path : exceptionModules.ref()) {
|
||||
result = aPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_SIGNED_BINARY,
|
||||
sandbox::TargetPolicy::SIGNED_ALLOW_LOAD, path);
|
||||
if (result != sandbox::SBOX_ALL_OK) {
|
||||
@ -1060,12 +1070,6 @@ bool SandboxBroker::SetSecurityLevelForRDDProcess() {
|
||||
sandbox::MITIGATION_DEP_NO_ATL_THUNK | sandbox::MITIGATION_DEP |
|
||||
sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32;
|
||||
|
||||
const Maybe<Vector<const wchar_t*>>& exceptionModules =
|
||||
GetPrespawnCigExceptionModules();
|
||||
if (exceptionModules.isSome()) {
|
||||
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
}
|
||||
|
||||
if (StaticPrefs::security_sandbox_rdd_shadow_stack_enabled()) {
|
||||
mitigations |= sandbox::MITIGATION_CET_COMPAT_MODE;
|
||||
}
|
||||
@ -1073,13 +1077,6 @@ bool SandboxBroker::SetSecurityLevelForRDDProcess() {
|
||||
result = mPolicy->SetProcessMitigations(mitigations);
|
||||
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.");
|
||||
}
|
||||
|
||||
mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER;
|
||||
|
||||
@ -1088,14 +1085,13 @@ bool SandboxBroker::SetSecurityLevelForRDDProcess() {
|
||||
mitigations |= DynamicCodeFlagForSystemMediaLibraries();
|
||||
}
|
||||
|
||||
if (exceptionModules.isNothing()) {
|
||||
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
}
|
||||
|
||||
result = mPolicy->SetDelayedProcessMitigations(mitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"Invalid flags for SetDelayedProcessMitigations.");
|
||||
|
||||
result = AddCigToPolicy(mPolicy);
|
||||
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.
|
||||
@ -1178,12 +1174,6 @@ bool SandboxBroker::SetSecurityLevelForSocketProcess() {
|
||||
sandbox::MITIGATION_DEP_NO_ATL_THUNK | sandbox::MITIGATION_DEP |
|
||||
sandbox::MITIGATION_IMAGE_LOAD_PREFER_SYS32;
|
||||
|
||||
const Maybe<Vector<const wchar_t*>>& exceptionModules =
|
||||
GetPrespawnCigExceptionModules();
|
||||
if (exceptionModules.isSome()) {
|
||||
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
}
|
||||
|
||||
if (StaticPrefs::security_sandbox_socket_shadow_stack_enabled()) {
|
||||
mitigations |= sandbox::MITIGATION_CET_COMPAT_MODE;
|
||||
}
|
||||
@ -1191,13 +1181,6 @@ bool SandboxBroker::SetSecurityLevelForSocketProcess() {
|
||||
result = mPolicy->SetProcessMitigations(mitigations);
|
||||
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.");
|
||||
}
|
||||
|
||||
if (StaticPrefs::security_sandbox_socket_win32k_disable()) {
|
||||
result = AddWin32kLockdownPolicy(mPolicy, false);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Failed to add the win32k lockdown policy");
|
||||
@ -1207,14 +1190,13 @@ bool SandboxBroker::SetSecurityLevelForSocketProcess() {
|
||||
sandbox::MITIGATION_DLL_SEARCH_ORDER |
|
||||
sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
|
||||
|
||||
if (exceptionModules.isNothing()) {
|
||||
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
|
||||
}
|
||||
|
||||
result = mPolicy->SetDelayedProcessMitigations(mitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"Invalid flags for SetDelayedProcessMitigations.");
|
||||
|
||||
result = AddCigToPolicy(mPolicy);
|
||||
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.
|
||||
@ -1382,53 +1364,26 @@ bool BuildUtilitySandbox(sandbox::TargetPolicy* policy,
|
||||
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);
|
||||
result = policy->SetProcessMitigations(us.mInitialMitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Invalid flags for SetProcessMitigations.");
|
||||
|
||||
result = policy->SetDelayedProcessMitigations(us.mDelayedMitigations);
|
||||
SANDBOX_ENSURE_SUCCESS(result,
|
||||
"Invalid flags for SetDelayedProcessMitigations.");
|
||||
|
||||
// Win32k lockdown might not work on earlier versions
|
||||
// Bug 1719212, 1769992
|
||||
if (IsWin10FallCreatorsUpdateOrLater() && us.mUseWin32kLockdown) {
|
||||
if (us.mUseWin32kLockdown && IsWin10FallCreatorsUpdateOrLater()) {
|
||||
result = AddWin32kLockdownPolicy(policy, false);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Failed to add the win32k lockdown policy");
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
// 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.");
|
||||
}
|
||||
bool alwaysProxyBinDirLoading = mozilla::HasPackageIdentity();
|
||||
result = AddCigToPolicy(policy, alwaysProxyBinDirLoading);
|
||||
SANDBOX_ENSURE_SUCCESS(result, "Failed to initialize signed policy rules.");
|
||||
}
|
||||
|
||||
result = policy->SetDelayedProcessMitigations(delayedMitigations);
|
||||
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
|
||||
// "chrome." so the sandboxed process cannot connect to system services.
|
||||
|
Loading…
Reference in New Issue
Block a user