# HG changeset patch # User Bob Owen # Date 1709836178 0 # Thu Mar 07 18:29:38 2024 +0000 # Node ID 2b9ab7e6c5a1630b497fe1543634cbaebdc395f8 # Parent f9c20c064d639a146ffa09ec832aee6dff44643d Bug 1889932 p1: Set process ACL to the delayed integrity level in LowerToken. r=yjuglaret! This allows us to maintain the same access to our process when the integrity level on our access token is dropped. This uses a lower level function for setting the label instead if the chromium wrappers, so that processes that haven't loaded ntmarta.dll don't need to. Differential Revision: https://phabricator.services.mozilla.com/D206784 diff --git a/sandbox/win/src/target_services.cc b/sandbox/win/src/target_services.cc --- a/sandbox/win/src/target_services.cc +++ b/sandbox/win/src/target_services.cc @@ -126,16 +126,39 @@ bool SetProcessIntegrityLevel(IntegrityLevel integrity_level) { base::win::AccessToken::FromCurrentProcess(/*impersonation=*/false, TOKEN_ADJUST_DEFAULT); if (!token) { return false; } return token->SetIntegrityLevel(*rid); } +void SetProcessAclIntegrityLevel(IntegrityLevel integrity_level) { + absl::optional rid = GetIntegrityLevelRid(integrity_level); + if (!rid) { + // No mandatory level specified, we don't change it. + return; + } + + // Set the integrity level for our process ACL, so we retain access to it. + // We ignore failures in non-debug because this is not a security measure, + // but some functionality may fail later in the process. + base::win::SecurityDescriptor sdWrapper; + if (!sdWrapper.SetMandatoryLabel(*rid, 0, 0)) { + DCHECK(false); + return; + } + + SECURITY_DESCRIPTOR sd; + sdWrapper.ToAbsolute(sd); + BOOL success = ::SetKernelObjectSecurity(::GetCurrentProcess(), + LABEL_SECURITY_INFORMATION, &sd); + DCHECK(success); +} + // Used as storage for g_target_services, because other allocation facilities // are not available early. We can't use a regular function static because on // VS2015, because the CRT tries to acquire a lock to guard initialization, but // this code runs before the CRT is initialized. char g_target_services_memory[sizeof(TargetServicesBase)]; TargetServicesBase* g_target_services = nullptr; } // namespace @@ -171,21 +194,23 @@ void TargetServicesBase::LowerToken() { if (ERROR_SUCCESS != ::RegDisablePredefinedCache()) ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CACHEDISABLE); if (!WarmupWindowsLocales()) ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_WARMUP); bool is_csrss_connected = true; if (!CloseOpenHandles(&is_csrss_connected)) ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CLOSEHANDLES); process_state_.SetCsrssConnected(is_csrss_connected); - // Enabling mitigations must happen last otherwise handle closing breaks + // Enabling mitigations must happen after the above measures otherwise handle + // closing breaks. if (g_shared_delayed_mitigations && !LockDownSecurityMitigations(g_shared_delayed_mitigations)) { ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_MITIGATION); } + SetProcessAclIntegrityLevel(g_shared_delayed_integrity_level); } ProcessState* TargetServicesBase::GetState() { return &process_state_; } TargetServicesBase* TargetServicesBase::GetInstance() { // Leak on purpose TargetServicesBase.