55
66#include " CommonCorePch.h"
77
8- #pragma section(".mrdata", read)
8+ #ifdef _WIN32
9+
10+ #include < VersionHelpers.h>
11+
912
1013CriticalSection GlobalSecurityPolicy::s_policyCS;
14+ GlobalSecurityPolicy GlobalSecurityObject;
15+
16+ #pragma section(".mrdata", read)
17+
18+ // Note: 'volatile' is necessary here otherwise the compiler assumes these are constants initialized to '0' and will constant propagate them...
19+ __declspec (allocate(" .mrdata" )) volatile GlobalSecurityPolicy::ReadOnlyData GlobalSecurityPolicy::readOnlyData =
20+ {
21+ #if defined(_CONTROL_FLOW_GUARD)
22+ nullptr ,
23+ nullptr ,
24+ #endif
25+ false ,
26+ false ,
27+ false
28+ };
29+
30+ bool
31+ GlobalSecurityPolicy::IsCFGEnabled ()
32+ {
33+ return readOnlyData.isCFGEnabled && !PHASE_OFF1 (Js::CFGPhase);
34+ }
35+
36+ bool
37+ GlobalSecurityPolicy::InitIsCFGEnabled ()
38+ {
39+ #if defined(_CONTROL_FLOW_GUARD)
40+ PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY CfgPolicy;
41+ BOOL isGetMitigationPolicySucceeded = GlobalSecurityPolicy::GetMitigationPolicyForProcess (
42+ GetCurrentProcess (),
43+ ProcessControlFlowGuardPolicy,
44+ &CfgPolicy,
45+ sizeof (CfgPolicy));
46+ AssertOrFailFast (isGetMitigationPolicySucceeded);
47+ return CfgPolicy.EnableControlFlowGuard ;
48+
49+ #else
50+ return false ;
51+ #endif // _CONTROL_FLOW_GUARD
52+ }
53+
54+ GlobalSecurityPolicy::GlobalSecurityPolicy ()
55+ {
56+ #if defined(_CONTROL_FLOW_GUARD)
57+ AutoCriticalSection autocs (&s_policyCS);
58+ DWORD oldProtect;
59+
60+ // Make sure this is called only once
61+ AssertOrFailFast (!readOnlyData.isInitialized );
62+
63+ #if defined(CHAKRA_CORE_DOWN_COMPAT)
64+ if (AutoSystemInfo::Data.IsWinThresholdOrLater ())
65+ #endif
66+ {
67+ // Make readOnlyData read-write
68+ BOOL res = VirtualProtect ((LPVOID)&readOnlyData, sizeof (ReadOnlyData), PAGE_READWRITE, &oldProtect);
69+ if ((res == FALSE ) || (oldProtect != PAGE_READONLY))
70+ {
71+ RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
72+ }
73+
74+ readOnlyData.isInitialized = true ;
75+
76+ EnsureFromSystemDirOnly ();
77+
78+ if (m_hModule)
79+ {
80+ readOnlyData.pfnGetProcessMitigationPolicy = (PFNCGetMitigationPolicyForProcess)GetFunction (" GetProcessMitigationPolicy" );
81+ if (readOnlyData.pfnGetProcessMitigationPolicy == nullptr )
82+ {
83+ RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
84+ }
85+
86+ readOnlyData.isCFGEnabled = InitIsCFGEnabled ();
87+
88+ if (readOnlyData.isCFGEnabled )
89+ {
90+ readOnlyData.pfnSetProcessValidCallTargets = (PFNCSetProcessValidCallTargets)GetFunction (" SetProcessValidCallTargets" );
91+ if (readOnlyData.pfnSetProcessValidCallTargets == nullptr )
92+ {
93+ RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
94+ }
95+ }
96+ }
97+
98+ // Make readOnlyData read-only again.
99+ res = VirtualProtect ((LPVOID)&readOnlyData, sizeof (ReadOnlyData), PAGE_READONLY, &oldProtect);
100+ if ((res == FALSE ) || (oldProtect != PAGE_READWRITE))
101+ {
102+ RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
103+ }
104+ }
11105
12- __declspec (allocate( " .mrdata " ))
13- volatile bool GlobalSecurityPolicy::s_ro_disableSetProcessValidCallTargets = false;
106+ # endif // _CONTROL_FLOW_GUARD
107+ }
14108
15109void
16110GlobalSecurityPolicy::DisableSetProcessValidCallTargets ()
17111{
18112 // One-way transition from allowing SetProcessValidCallTargets to disabling
19113 // the API.
20- if (!s_ro_disableSetProcessValidCallTargets )
114+ if (!readOnlyData. disableSetProcessValidCallTargets )
21115 {
22116 AutoCriticalSection autocs (&s_policyCS);
23117 DWORD oldProtect;
24118
25- BOOL res = VirtualProtect ((LPVOID)&s_ro_disableSetProcessValidCallTargets , sizeof (s_ro_disableSetProcessValidCallTargets ), PAGE_READWRITE, &oldProtect);
119+ BOOL res = VirtualProtect ((LPVOID)&readOnlyData , sizeof (ReadOnlyData ), PAGE_READWRITE, &oldProtect);
26120 if ((res == FALSE ) || (oldProtect != PAGE_READONLY))
27121 {
28122 RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
29123 }
30124
31- s_ro_disableSetProcessValidCallTargets = true ;
125+ readOnlyData. disableSetProcessValidCallTargets = true ;
32126
33- res = VirtualProtect ((LPVOID)&s_ro_disableSetProcessValidCallTargets , sizeof (s_ro_disableSetProcessValidCallTargets ), PAGE_READONLY, &oldProtect);
127+ res = VirtualProtect ((LPVOID)&readOnlyData , sizeof (ReadOnlyData ), PAGE_READONLY, &oldProtect);
34128 if ((res == FALSE ) || (oldProtect != PAGE_READWRITE))
35129 {
36130 RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
@@ -41,5 +135,20 @@ GlobalSecurityPolicy::DisableSetProcessValidCallTargets()
41135bool
42136GlobalSecurityPolicy::IsSetProcessValidCallTargetsAllowed ()
43137{
44- return !s_ro_disableSetProcessValidCallTargets;
138+ return !readOnlyData.disableSetProcessValidCallTargets ;
139+ }
140+
141+ #if defined(_CONTROL_FLOW_GUARD)
142+ BOOL
143+ DECLSPEC_GUARDNOCF GlobalSecurityPolicy::GetMitigationPolicyForProcess (HANDLE hProcess, PROCESS_MITIGATION_POLICY mitigationPolicy, PVOID lpBuffer, SIZE_T dwLength)
144+ {
145+ return GlobalSecurityPolicy::readOnlyData.pfnGetProcessMitigationPolicy (hProcess, mitigationPolicy, lpBuffer, dwLength);
146+ }
147+
148+ BOOL
149+ DECLSPEC_GUARDNOCF GlobalSecurityPolicy::SetProcessValidCallTargets (HANDLE hProcess, PVOID virtualAddress, SIZE_T regionSize, ULONG numberOfOffsets, PCFG_CALL_TARGET_INFO offsetInformation)
150+ {
151+ return GlobalSecurityPolicy::readOnlyData.pfnSetProcessValidCallTargets (hProcess, virtualAddress, regionSize, numberOfOffsets, offsetInformation);
45152}
153+ #endif // _CONTROL_FLOW_GUARD
154+ #endif // _WIN32
0 commit comments