32_set_delayed_integrity_on_process_acl.patch (3481B)
1 # HG changeset patch 2 # User Bob Owen <bobowencode@gmail.com> 3 # Date 1709836178 0 4 # Thu Mar 07 18:29:38 2024 +0000 5 # Node ID 2b9ab7e6c5a1630b497fe1543634cbaebdc395f8 6 # Parent f9c20c064d639a146ffa09ec832aee6dff44643d 7 Bug 1889932 p1: Set process ACL to the delayed integrity level in LowerToken. r=yjuglaret! 8 9 This allows us to maintain the same access to our process when the integrity 10 level on our access token is dropped. 11 This uses a lower level function for setting the label instead if the chromium 12 wrappers, so that processes that haven't loaded ntmarta.dll don't need to. 13 14 Differential Revision: https://phabricator.services.mozilla.com/D206784 15 16 diff --git a/sandbox/win/src/target_services.cc b/sandbox/win/src/target_services.cc 17 --- a/sandbox/win/src/target_services.cc 18 +++ b/sandbox/win/src/target_services.cc 19 @@ -126,16 +126,39 @@ bool SetProcessIntegrityLevel(IntegrityLevel integrity_level) { 20 base::win::AccessToken::FromCurrentProcess(/*impersonation=*/false, 21 TOKEN_ADJUST_DEFAULT); 22 if (!token) { 23 return false; 24 } 25 return token->SetIntegrityLevel(*rid); 26 } 27 28 +void SetProcessAclIntegrityLevel(IntegrityLevel integrity_level) { 29 + absl::optional<DWORD> rid = GetIntegrityLevelRid(integrity_level); 30 + if (!rid) { 31 + // No mandatory level specified, we don't change it. 32 + return; 33 + } 34 + 35 + // Set the integrity level for our process ACL, so we retain access to it. 36 + // We ignore failures in non-debug because this is not a security measure, 37 + // but some functionality may fail later in the process. 38 + base::win::SecurityDescriptor sdWrapper; 39 + if (!sdWrapper.SetMandatoryLabel(*rid, 0, 0)) { 40 + DCHECK(false); 41 + return; 42 + } 43 + 44 + SECURITY_DESCRIPTOR sd; 45 + sdWrapper.ToAbsolute(sd); 46 + BOOL success = ::SetKernelObjectSecurity(::GetCurrentProcess(), 47 + LABEL_SECURITY_INFORMATION, &sd); 48 + DCHECK(success); 49 +} 50 + 51 // Used as storage for g_target_services, because other allocation facilities 52 // are not available early. We can't use a regular function static because on 53 // VS2015, because the CRT tries to acquire a lock to guard initialization, but 54 // this code runs before the CRT is initialized. 55 char g_target_services_memory[sizeof(TargetServicesBase)]; 56 TargetServicesBase* g_target_services = nullptr; 57 58 } // namespace 59 @@ -171,21 +194,23 @@ void TargetServicesBase::LowerToken() { 60 if (ERROR_SUCCESS != ::RegDisablePredefinedCache()) 61 ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CACHEDISABLE); 62 if (!WarmupWindowsLocales()) 63 ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_WARMUP); 64 bool is_csrss_connected = true; 65 if (!CloseOpenHandles(&is_csrss_connected)) 66 ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_CLOSEHANDLES); 67 process_state_.SetCsrssConnected(is_csrss_connected); 68 - // Enabling mitigations must happen last otherwise handle closing breaks 69 + // Enabling mitigations must happen after the above measures otherwise handle 70 + // closing breaks. 71 if (g_shared_delayed_mitigations && 72 !LockDownSecurityMitigations(g_shared_delayed_mitigations)) { 73 ::TerminateProcess(::GetCurrentProcess(), SBOX_FATAL_MITIGATION); 74 } 75 + SetProcessAclIntegrityLevel(g_shared_delayed_integrity_level); 76 } 77 78 ProcessState* TargetServicesBase::GetState() { 79 return &process_state_; 80 } 81 82 TargetServicesBase* TargetServicesBase::GetInstance() { 83 // Leak on purpose TargetServicesBase.