Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Build/Common.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
21 changes: 21 additions & 0 deletions bin/ch/ch.manifest
Original file line number Diff line number Diff line change
@@ -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>
5 changes: 4 additions & 1 deletion bin/ch/ch.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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>
2 changes: 1 addition & 1 deletion lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) ||
Expand Down
8 changes: 7 additions & 1 deletion lib/Common/CommonDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
1 change: 1 addition & 0 deletions lib/Common/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ add_library (Chakra.Common.Core OBJECT
DelayLoadLibrary.cpp
EtwTraceCore.cpp
FaultInjection.cpp
GlobalSecurityPolicy.cpp
Output.cpp
PerfCounter.cpp
PerfCounterImpl.cpp
Expand Down
125 changes: 117 additions & 8 deletions lib/Common/Core/GlobalSecurityPolicy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
36 changes: 34 additions & 2 deletions lib/Common/Core/GlobalSecurityPolicy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
};
14 changes: 0 additions & 14 deletions lib/Common/Core/SysInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
1 change: 0 additions & 1 deletion lib/Common/Core/SysInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
12 changes: 6 additions & 6 deletions lib/Common/Memory/CustomHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Common/Memory/PageAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
{
Expand Down
4 changes: 2 additions & 2 deletions lib/Common/Memory/SectionAllocWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Loading