Skip to content
Permalink
Browse files

[MERGE #6355 @pleath] Port CFG enabling changes to release 1.11

Merge pull request #6355 from pleath:cfg-1.11
  • Loading branch information
pleath committed Dec 17, 2019
2 parents 4874bbc + 76a06a2 commit cd965539b9529430730c478e677269ab1706bdee
@@ -65,6 +65,8 @@
<!-- /Gy -->
<FunctionLevelLinking>true</FunctionLevelLinking>
<!-- /GF -->
<ControlFlowGuard Condition="'$(Platform)'!='ARM'">Guard</ControlFlowGuard>
<!-- /guard:cf -->
<StringPooling>true</StringPooling>
<!-- /MD -->
<RuntimeLibrary Condition="'$(RuntimeLib)'!='static_library'">MultiThreadedDLL</RuntimeLibrary>
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="Microsoft.Chakra.ch.exe"
version="1.0.0.0"
type="win32" />
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
<!-- Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!-- Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!-- Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!-- Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
</application>
</compatibility>
</assembly>
@@ -123,6 +123,9 @@
<Authenticode>Microsoft400</Authenticode>
</FilesToSign>
</ItemGroup>
<ItemGroup>
<Manifest Include="ch.manifest" />
</ItemGroup>
<Import Project="$(BuildConfigPropsPath)Chakra.Build.targets" Condition="exists('$(BuildConfigPropsPath)Chakra.Build.targets')" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>
</Project>
@@ -5285,7 +5285,7 @@ GlobOpt::ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal)
}
}
}

IR::IndirOpnd *src = instr->GetSrc1()->AsIndirOpnd();
const ValueType baseValueType(src->GetBaseOpnd()->GetValueType());
if (instr->DoStackArgsOpt(this->func) ||
@@ -12,6 +12,10 @@
#include "Warnings.h"
#include "ChakraCoreVersion.h"

// CFG was never enabled for ARM32 and requires WIN10 SDK
#if !defined(_M_ARM) && defined(_WIN32) && defined(NTDDI_WIN10)
#define _CONTROL_FLOW_GUARD 1
#endif

//----------------------------------------------------------------------------------------------------
// Default debug/fretest/release flags values
@@ -316,7 +320,9 @@
#endif

// Other features
// #define CHAKRA_CORE_DOWN_COMPAT 1
#if defined(_CHAKRACOREBUILD)
# define CHAKRA_CORE_DOWN_COMPAT 1
#endif

// todo:: Enable vectorcall on NTBUILD. OS#13609380
#if defined(_WIN32) && !defined(NTBUILD) && defined(_M_IX86)
@@ -11,6 +11,7 @@ add_library (Chakra.Common.Core OBJECT
DelayLoadLibrary.cpp
EtwTraceCore.cpp
FaultInjection.cpp
GlobalSecurityPolicy.cpp
Output.cpp
PerfCounter.cpp
PerfCounterImpl.cpp
@@ -5,32 +5,126 @@

#include "CommonCorePch.h"

#pragma section(".mrdata", read)
#ifdef _WIN32

#include <VersionHelpers.h>


CriticalSection GlobalSecurityPolicy::s_policyCS;
GlobalSecurityPolicy GlobalSecurityObject;

#pragma section(".mrdata", read)

// Note: 'volatile' is necessary here otherwise the compiler assumes these are constants initialized to '0' and will constant propagate them...
__declspec(allocate(".mrdata")) volatile GlobalSecurityPolicy::ReadOnlyData GlobalSecurityPolicy::readOnlyData =
{
#if defined(_CONTROL_FLOW_GUARD)
nullptr,
nullptr,
#endif
false,
false,
false
};

bool
GlobalSecurityPolicy::IsCFGEnabled()
{
return readOnlyData.isCFGEnabled && !PHASE_OFF1(Js::CFGPhase);
}

bool
GlobalSecurityPolicy::InitIsCFGEnabled()
{
#if defined(_CONTROL_FLOW_GUARD)
PROCESS_MITIGATION_CONTROL_FLOW_GUARD_POLICY CfgPolicy;
BOOL isGetMitigationPolicySucceeded = GlobalSecurityPolicy::GetMitigationPolicyForProcess(
GetCurrentProcess(),
ProcessControlFlowGuardPolicy,
&CfgPolicy,
sizeof(CfgPolicy));
AssertOrFailFast(isGetMitigationPolicySucceeded);
return CfgPolicy.EnableControlFlowGuard;

#else
return false;
#endif // _CONTROL_FLOW_GUARD
}

GlobalSecurityPolicy::GlobalSecurityPolicy()
{
#if defined(_CONTROL_FLOW_GUARD)
AutoCriticalSection autocs(&s_policyCS);
DWORD oldProtect;

// Make sure this is called only once
AssertOrFailFast(!readOnlyData.isInitialized);

#if defined(CHAKRA_CORE_DOWN_COMPAT)
if (AutoSystemInfo::Data.IsWinThresholdOrLater())
#endif
{
// Make readOnlyData read-write
BOOL res = VirtualProtect((LPVOID)&readOnlyData, sizeof(ReadOnlyData), PAGE_READWRITE, &oldProtect);
if ((res == FALSE) || (oldProtect != PAGE_READONLY))
{
RaiseFailFastException(nullptr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
}

readOnlyData.isInitialized = true;

EnsureFromSystemDirOnly();

if (m_hModule)
{
readOnlyData.pfnGetProcessMitigationPolicy = (PFNCGetMitigationPolicyForProcess)GetFunction("GetProcessMitigationPolicy");
if (readOnlyData.pfnGetProcessMitigationPolicy == nullptr)
{
RaiseFailFastException(nullptr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
}

readOnlyData.isCFGEnabled = InitIsCFGEnabled();

if (readOnlyData.isCFGEnabled)
{
readOnlyData.pfnSetProcessValidCallTargets = (PFNCSetProcessValidCallTargets)GetFunction("SetProcessValidCallTargets");
if (readOnlyData.pfnSetProcessValidCallTargets == nullptr)
{
RaiseFailFastException(nullptr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
}
}
}

// Make readOnlyData read-only again.
res = VirtualProtect((LPVOID)&readOnlyData, sizeof(ReadOnlyData), PAGE_READONLY, &oldProtect);
if ((res == FALSE) || (oldProtect != PAGE_READWRITE))
{
RaiseFailFastException(nullptr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
}
}

__declspec(allocate(".mrdata"))
volatile bool GlobalSecurityPolicy::s_ro_disableSetProcessValidCallTargets = false;
#endif //_CONTROL_FLOW_GUARD
}

void
GlobalSecurityPolicy::DisableSetProcessValidCallTargets()
{
// One-way transition from allowing SetProcessValidCallTargets to disabling
// the API.
if (!s_ro_disableSetProcessValidCallTargets)
if (!readOnlyData.disableSetProcessValidCallTargets)
{
AutoCriticalSection autocs(&s_policyCS);
DWORD oldProtect;

BOOL res = VirtualProtect((LPVOID)&s_ro_disableSetProcessValidCallTargets, sizeof(s_ro_disableSetProcessValidCallTargets), PAGE_READWRITE, &oldProtect);
BOOL res = VirtualProtect((LPVOID)&readOnlyData, sizeof(ReadOnlyData), PAGE_READWRITE, &oldProtect);
if ((res == FALSE) || (oldProtect != PAGE_READONLY))
{
RaiseFailFastException(nullptr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
}

s_ro_disableSetProcessValidCallTargets = true;
readOnlyData.disableSetProcessValidCallTargets = true;

res = VirtualProtect((LPVOID)&s_ro_disableSetProcessValidCallTargets, sizeof(s_ro_disableSetProcessValidCallTargets), PAGE_READONLY, &oldProtect);
res = VirtualProtect((LPVOID)&readOnlyData, sizeof(ReadOnlyData), PAGE_READONLY, &oldProtect);
if ((res == FALSE) || (oldProtect != PAGE_READWRITE))
{
RaiseFailFastException(nullptr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
@@ -41,5 +135,20 @@ GlobalSecurityPolicy::DisableSetProcessValidCallTargets()
bool
GlobalSecurityPolicy::IsSetProcessValidCallTargetsAllowed()
{
return !s_ro_disableSetProcessValidCallTargets;
return !readOnlyData.disableSetProcessValidCallTargets;
}

#if defined(_CONTROL_FLOW_GUARD)
BOOL
DECLSPEC_GUARDNOCF GlobalSecurityPolicy::GetMitigationPolicyForProcess(HANDLE hProcess, PROCESS_MITIGATION_POLICY mitigationPolicy, PVOID lpBuffer, SIZE_T dwLength)
{
return GlobalSecurityPolicy::readOnlyData.pfnGetProcessMitigationPolicy(hProcess, mitigationPolicy, lpBuffer, dwLength);
}

BOOL
DECLSPEC_GUARDNOCF GlobalSecurityPolicy::SetProcessValidCallTargets(HANDLE hProcess, PVOID virtualAddress, SIZE_T regionSize, ULONG numberOfOffsets, PCFG_CALL_TARGET_INFO offsetInformation)
{
return GlobalSecurityPolicy::readOnlyData.pfnSetProcessValidCallTargets(hProcess, virtualAddress, regionSize, numberOfOffsets, offsetInformation);
}
#endif //_CONTROL_FLOW_GUARD
#endif // _WIN32
@@ -4,14 +4,46 @@
//-------------------------------------------------------------------------------------------------------
#pragma once

class GlobalSecurityPolicy
#include "DelayLoadLibrary.h"

class GlobalSecurityPolicy : private DelayLoadLibrary
{
public:
#ifdef _WIN32
#if defined(_CONTROL_FLOW_GUARD)
typedef BOOL FNCGetMitigationPolicyForProcess(HANDLE, PROCESS_MITIGATION_POLICY, PVOID, SIZE_T);
typedef FNCGetMitigationPolicyForProcess* PFNCGetMitigationPolicyForProcess;

typedef BOOL FNCSetProcessValidCallTargets(HANDLE, PVOID, SIZE_T, ULONG, PCFG_CALL_TARGET_INFO);
typedef FNCSetProcessValidCallTargets* PFNCSetProcessValidCallTargets;
#endif
GlobalSecurityPolicy();

static void DisableSetProcessValidCallTargets();
static bool IsSetProcessValidCallTargetsAllowed();
static bool IsCFGEnabled();

#if defined(_CONTROL_FLOW_GUARD)
static FNCGetMitigationPolicyForProcess GetMitigationPolicyForProcess;
static FNCSetProcessValidCallTargets SetProcessValidCallTargets;
#endif
LPCTSTR GetLibraryName() const { return _u("api-ms-win-core-memory-l1-1-3.dll"); }

private:
static CriticalSection s_policyCS;

static volatile bool s_ro_disableSetProcessValidCallTargets;
volatile static struct ReadOnlyData {
#if defined(_CONTROL_FLOW_GUARD)
PFNCGetMitigationPolicyForProcess pfnGetProcessMitigationPolicy;
PFNCSetProcessValidCallTargets pfnSetProcessValidCallTargets;
#endif
bool disableSetProcessValidCallTargets;
bool isCFGEnabled;
bool isInitialized;
} readOnlyData;

static bool InitIsCFGEnabled();
#else
static bool IsCFGEnabled() { return false; }
#endif
};
@@ -360,20 +360,6 @@ AutoSystemInfo::CheckForAtom() const
}
#endif

bool
AutoSystemInfo::IsCFGEnabled()
{
#if defined(_CONTROL_FLOW_GUARD)
return true
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
&& IsWinThresholdOrLater() && !PHASE_OFF1(Js::CFGPhase)
#endif //ENABLE_DEBUG_CONFIG_OPTIONS
;
#else
return false;
#endif //_CONTROL_FLOW_GUARD
}

bool
AutoSystemInfo::IsWin8OrLater()
{
@@ -15,7 +15,6 @@ class AutoSystemInfo : public SYSTEM_INFO
uint GetAllocationGranularityPageSize() const;

bool DisableDebugScopeCapture() const { return this->disableDebugScopeCapture; }
bool IsCFGEnabled();
bool IsWin8OrLater();
#if defined(_CONTROL_FLOW_GUARD)
bool IsWinThresholdOrLater();
@@ -288,7 +288,7 @@ BOOL Heap<TAlloc, TPreReservedAlloc>::ProtectAllocationWithExecuteReadWrite(Allo
{
DWORD protectFlags = 0;

if (AutoSystemInfo::Data.IsCFGEnabled())
if (GlobalSecurityPolicy::IsCFGEnabled())
{
protectFlags = PAGE_EXECUTE_RW_TARGETS_NO_UPDATE;
}
@@ -303,7 +303,7 @@ template<typename TAlloc, typename TPreReservedAlloc>
BOOL Heap<TAlloc, TPreReservedAlloc>::ProtectAllocationWithExecuteReadOnly(__in Allocation *allocation, __in_opt char* addressInPage)
{
DWORD protectFlags = 0;
if (AutoSystemInfo::Data.IsCFGEnabled())
if (GlobalSecurityPolicy::IsCFGEnabled())
{
protectFlags = PAGE_EXECUTE_RO_TARGETS_NO_UPDATE;
}
@@ -417,7 +417,7 @@ Allocation* Heap<TAlloc, TPreReservedAlloc>::AllocLargeObject(size_t bytes, usho
if (this->processHandle == GetCurrentProcess())
{
DWORD protectFlags = 0;
if (AutoSystemInfo::Data.IsCFGEnabled())
if (GlobalSecurityPolicy::IsCFGEnabled())
{
protectFlags = PAGE_EXECUTE_RO_TARGETS_NO_UPDATE;
}
@@ -513,7 +513,7 @@ DWORD Heap<TAlloc, TPreReservedAlloc>::EnsureAllocationWriteable(Allocation* all
template<typename TAlloc, typename TPreReservedAlloc>
DWORD Heap<TAlloc, TPreReservedAlloc>::EnsureAllocationExecuteWriteable(Allocation* allocation)
{
if (AutoSystemInfo::Data.IsCFGEnabled())
if (GlobalSecurityPolicy::IsCFGEnabled())
{
return EnsureAllocationReadWrite<PAGE_EXECUTE_RW_TARGETS_NO_UPDATE>(allocation);
}
@@ -685,7 +685,7 @@ Page* Heap<TAlloc, TPreReservedAlloc>::AllocNewPage(BucketId bucket, bool canAll

DWORD protectFlags = 0;

if (AutoSystemInfo::Data.IsCFGEnabled())
if (GlobalSecurityPolicy::IsCFGEnabled())
{
protectFlags = PAGE_EXECUTE_RO_TARGETS_NO_UPDATE;
}
@@ -885,7 +885,7 @@ bool Heap<TAlloc, TPreReservedAlloc>::FreeAllocation(Allocation* object)

DWORD protectFlags = 0;

if (AutoSystemInfo::Data.IsCFGEnabled())
if (GlobalSecurityPolicy::IsCFGEnabled())
{
protectFlags = PAGE_EXECUTE_RO_TARGETS_NO_UPDATE;
}
@@ -2665,7 +2665,7 @@ HeapPageAllocator<T>::ProtectPages(__in char* address, size_t pageCount, __in vo

/*Verify if we always pass the PAGE_TARGETS_NO_UPDATE flag, if the protect flag is EXECUTE*/
#if defined(_CONTROL_FLOW_GUARD)
if (AutoSystemInfo::Data.IsCFGEnabled() &&
if (GlobalSecurityPolicy::IsCFGEnabled() &&
(dwVirtualProtectFlags & (PAGE_EXECUTE | PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE)) &&
((dwVirtualProtectFlags & PAGE_TARGETS_NO_UPDATE) == 0))
{
@@ -99,7 +99,7 @@ PVOID MapView(HANDLE process, HANDLE sectionHandle, size_t size, size_t offset,
{
return nullptr;
}
flags = AutoSystemInfo::Data.IsCFGEnabled() ? PAGE_EXECUTE_RO_TARGETS_INVALID : PAGE_EXECUTE_READ;
flags = GlobalSecurityPolicy::IsCFGEnabled() ? PAGE_EXECUTE_RO_TARGETS_INVALID : PAGE_EXECUTE_READ;
}

#if USEFILEMAP2
@@ -860,7 +860,7 @@ LPVOID PreReservedSectionAllocWrapper::EnsurePreReservedRegionInternal()
#endif // _M_IX86
#endif

if (AutoSystemInfo::Data.IsCFGEnabled() && supportPreReservedRegion)
if (GlobalSecurityPolicy::IsCFGEnabled() && supportPreReservedRegion)
{
HANDLE sectionHandle = CreateSection(bytes, false);
if (sectionHandle == nullptr)

0 comments on commit cd96553

Please sign in to comment.
You can’t perform that action at this time.