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+ }
1135
12- __declspec (allocate(" .mrdata" ))
13- volatile bool GlobalSecurityPolicy::s_ro_disableSetProcessValidCallTargets = false;
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+
105+ #if defined (NTBUILD)
106+ AssertOrFailFast (readOnlyData.isCFGEnabled );
107+ #endif
108+ }
109+
110+ #endif // _CONTROL_FLOW_GUARD
111+ }
14112
15113void
16114GlobalSecurityPolicy::DisableSetProcessValidCallTargets ()
17115{
18116 // One-way transition from allowing SetProcessValidCallTargets to disabling
19117 // the API.
20- if (!s_ro_disableSetProcessValidCallTargets )
118+ if (!readOnlyData. disableSetProcessValidCallTargets )
21119 {
22120 AutoCriticalSection autocs (&s_policyCS);
23121 DWORD oldProtect;
24122
25- BOOL res = VirtualProtect ((LPVOID)&s_ro_disableSetProcessValidCallTargets , sizeof (s_ro_disableSetProcessValidCallTargets ), PAGE_READWRITE, &oldProtect);
123+ BOOL res = VirtualProtect ((LPVOID)&readOnlyData , sizeof (ReadOnlyData ), PAGE_READWRITE, &oldProtect);
26124 if ((res == FALSE ) || (oldProtect != PAGE_READONLY))
27125 {
28126 RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
29127 }
30128
31- s_ro_disableSetProcessValidCallTargets = true ;
129+ readOnlyData. disableSetProcessValidCallTargets = true ;
32130
33- res = VirtualProtect ((LPVOID)&s_ro_disableSetProcessValidCallTargets , sizeof (s_ro_disableSetProcessValidCallTargets ), PAGE_READONLY, &oldProtect);
131+ res = VirtualProtect ((LPVOID)&readOnlyData , sizeof (ReadOnlyData ), PAGE_READONLY, &oldProtect);
34132 if ((res == FALSE ) || (oldProtect != PAGE_READWRITE))
35133 {
36134 RaiseFailFastException (nullptr , nullptr , FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
@@ -41,5 +139,20 @@ GlobalSecurityPolicy::DisableSetProcessValidCallTargets()
41139bool
42140GlobalSecurityPolicy::IsSetProcessValidCallTargetsAllowed ()
43141{
44- return !s_ro_disableSetProcessValidCallTargets;
142+ return !readOnlyData.disableSetProcessValidCallTargets ;
143+ }
144+
145+ #if defined(_CONTROL_FLOW_GUARD)
146+ BOOL
147+ DECLSPEC_GUARDNOCF GlobalSecurityPolicy::GetMitigationPolicyForProcess (HANDLE hProcess, PROCESS_MITIGATION_POLICY mitigationPolicy, PVOID lpBuffer, SIZE_T dwLength)
148+ {
149+ return GlobalSecurityPolicy::readOnlyData.pfnGetProcessMitigationPolicy (hProcess, mitigationPolicy, lpBuffer, dwLength);
150+ }
151+
152+ BOOL
153+ DECLSPEC_GUARDNOCF GlobalSecurityPolicy::SetProcessValidCallTargets (HANDLE hProcess, PVOID virtualAddress, SIZE_T regionSize, ULONG numberOfOffsets, PCFG_CALL_TARGET_INFO offsetInformation)
154+ {
155+ return GlobalSecurityPolicy::readOnlyData.pfnSetProcessValidCallTargets (hProcess, virtualAddress, regionSize, numberOfOffsets, offsetInformation);
45156}
157+ #endif // _CONTROL_FLOW_GUARD
158+ #endif // _WIN32
0 commit comments