From 42385c444b3a27f308007f0ffb2c8037ac501eb9 Mon Sep 17 00:00:00 2001 From: CHUNSEOK LEE Date: Thu, 3 Aug 2017 13:21:29 +0900 Subject: poison added Change-Id: I71ac60336159706bb44797ef9c64131d76560b23 --- packaging/coreclr.spec | 7 +- packaging/poison1.patch | 418 ++++++++++++++++++++++++++++++++++++++++++++++++ packaging/poison2.patch | 25 +++ 3 files changed, 449 insertions(+), 1 deletion(-) create mode 100644 packaging/poison1.patch create mode 100644 packaging/poison2.patch (limited to 'packaging') diff --git a/packaging/coreclr.spec b/packaging/coreclr.spec index 72695a0aad..773064873e 100644 --- a/packaging/coreclr.spec +++ b/packaging/coreclr.spec @@ -23,7 +23,7 @@ Source1000: downloaded_files.tar.gz Source1001: %{name}.manifest Source1002: libicu.tar.gz Source1003: dep_libs.tar.gz -# Gbp-Ignore-Patches: 0 1 2 3 4 5 6 7 8 9 10 11 12 +# Gbp-Ignore-Patches: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Patch0: Add-project.assets.json-files.patch Patch1: Add-Tizen-RuntimeID-case.patch Patch2: Change-O3-build-in-clang3.8.patch @@ -37,6 +37,8 @@ Patch9: Set-local-variables-as-addr-exposed-if-it-appears-in.patch Patch10: Revert-unnecessary-changes.patch Patch11: Add-skipped-testcase-superpmi.patch Patch12: tizen-toolchain-support.patch +Patch13: poison1.patch +Patch14: poison2.patch ExcludeArch: aarch64 @@ -141,6 +143,9 @@ cp %{SOURCE1001} . %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 +%patch14 -p1 + %if 0%{skipmscorlib} %else cp %{SOURCE1000} ./ diff --git a/packaging/poison1.patch b/packaging/poison1.patch new file mode 100644 index 0000000000..b1d4336a1c --- /dev/null +++ b/packaging/poison1.patch @@ -0,0 +1,418 @@ +From 1c540c594cc55d8446086dcd979c48efa84e00a9 Mon Sep 17 00:00:00 2001 +From: Jonghyun Park +Date: Mon, 31 Jul 2017 16:48:16 +0900 +Subject: [PATCH] Fill freed loader heap chunk with non-zero value (#12731) + +* Add FEATURE_LOADER_HEAP_GUARD feature + +* Invoke memset only for reclaimed regions + +* Enable FEATURE_LOADER_HEAP_GUARD by default + +* Insert trap inside UMEntryThunk::Terminate + +* Make all exectuable heaps not to zero-initialize itself + +Use fZeroInit (instead of fMakeRelazed) + +* Add comment + +* Revert unnecessary changes + +* Add and use 'Poison' method to insert a trap + +* Do NOT invoke FlushInstructionCache + +* Update comment + +* Add comment on ARM Poisoning instruction + +* Use X86_INSTR_INT3 instead of 0xCC +--- + src/inc/loaderheap.h | 23 +++++++++++++---------- + src/utilcode/loaderheap.cpp | 35 ++++++++++++++++++++++++++--------- + src/vm/amd64/cgenamd64.cpp | 13 +++++++++++++ + src/vm/amd64/cgencpu.h | 1 + + src/vm/arm/cgencpu.h | 1 + + src/vm/arm/stubs.cpp | 6 ++++++ + src/vm/arm64/cgencpu.h | 1 + + src/vm/arm64/stubs.cpp | 4 ++++ + src/vm/dllimportcallback.cpp | 12 +++--------- + src/vm/dllimportcallback.h | 4 ---- + src/vm/i386/cgencpu.h | 1 + + src/vm/i386/cgenx86.cpp | 7 +++++++ + src/vm/loaderallocator.cpp | 4 +++- + 13 files changed, 79 insertions(+), 33 deletions(-) + +diff --git a/src/inc/loaderheap.h b/src/inc/loaderheap.h +index 7d4c48f5e86..4333505e839 100644 +--- a/src/inc/loaderheap.h ++++ b/src/inc/loaderheap.h +@@ -217,7 +217,7 @@ class UnlockedLoaderHeap + + size_t * m_pPrivatePerfCounter_LoaderBytes; + +- DWORD m_flProtect; ++ DWORD m_Options; + + LoaderHeapFreeBlock *m_pFirstFreeBlock; + +@@ -288,7 +288,8 @@ class UnlockedLoaderHeap + SIZE_T dwReservedRegionSize, + size_t *pPrivatePerfCounter_LoaderBytes = NULL, + RangeList *pRangeList = NULL, +- BOOL fMakeExecutable = FALSE); ++ BOOL fMakeExecutable = FALSE, ++ BOOL fZeroInit = TRUE); + + ~UnlockedLoaderHeap(); + #endif +@@ -398,10 +399,8 @@ class UnlockedLoaderHeap + return m_dwTotalAlloc; + } + +- BOOL IsExecutable() +- { +- return (PAGE_EXECUTE_READWRITE == m_flProtect); +- } ++ BOOL IsExecutable(); ++ BOOL IsZeroInit(); + + + public: +@@ -447,14 +446,16 @@ class LoaderHeap : public UnlockedLoaderHeap, public ILoaderHeapBackout + DWORD dwCommitBlockSize, + size_t *pPrivatePerfCounter_LoaderBytes = NULL, + RangeList *pRangeList = NULL, +- BOOL fMakeExecutable = FALSE ++ BOOL fMakeExecutable = FALSE, ++ BOOL fZeroInit = TRUE + ) + : UnlockedLoaderHeap(dwReserveBlockSize, + dwCommitBlockSize, + NULL, 0, + pPrivatePerfCounter_LoaderBytes, + pRangeList, +- fMakeExecutable) ++ fMakeExecutable, ++ fZeroInit) + { + WRAPPER_NO_CONTRACT; + m_CriticalSection = NULL; +@@ -469,7 +470,8 @@ class LoaderHeap : public UnlockedLoaderHeap, public ILoaderHeapBackout + SIZE_T dwReservedRegionSize, + size_t *pPrivatePerfCounter_LoaderBytes = NULL, + RangeList *pRangeList = NULL, +- BOOL fMakeExecutable = FALSE ++ BOOL fMakeExecutable = FALSE, ++ BOOL fZeroInit = TRUE + ) + : UnlockedLoaderHeap(dwReserveBlockSize, + dwCommitBlockSize, +@@ -477,7 +479,8 @@ class LoaderHeap : public UnlockedLoaderHeap, public ILoaderHeapBackout + dwReservedRegionSize, + pPrivatePerfCounter_LoaderBytes, + pRangeList, +- fMakeExecutable) ++ fMakeExecutable, ++ fZeroInit) + { + WRAPPER_NO_CONTRACT; + m_CriticalSection = NULL; +diff --git a/src/utilcode/loaderheap.cpp b/src/utilcode/loaderheap.cpp +index 3f1063ce8e3..2603a8ec333 100644 +--- a/src/utilcode/loaderheap.cpp ++++ b/src/utilcode/loaderheap.cpp +@@ -10,6 +10,9 @@ + #define DONOT_DEFINE_ETW_CALLBACK + #include "eventtracebase.h" + ++#define LHF_EXECUTABLE 0x1 ++#define LHF_ZEROINIT 0x2 ++ + #ifndef DACCESS_COMPILE + + INDEBUG(DWORD UnlockedLoaderHeap::s_dwNumInstancesOfLoaderHeaps = 0;) +@@ -903,7 +906,8 @@ UnlockedLoaderHeap::UnlockedLoaderHeap(DWORD dwReserveBlockSize, + SIZE_T dwReservedRegionSize, + size_t *pPrivatePerfCounter_LoaderBytes, + RangeList *pRangeList, +- BOOL fMakeExecutable) ++ BOOL fMakeExecutable, ++ BOOL fZeroInit) + { + CONTRACTL + { +@@ -939,10 +943,11 @@ UnlockedLoaderHeap::UnlockedLoaderHeap(DWORD dwReserveBlockSize, + + m_pPrivatePerfCounter_LoaderBytes = pPrivatePerfCounter_LoaderBytes; + ++ m_Options = 0; + if (fMakeExecutable) +- m_flProtect = PAGE_EXECUTE_READWRITE; +- else +- m_flProtect = PAGE_READWRITE; ++ m_Options |= LHF_EXECUTABLE; ++ if (fZeroInit) ++ m_Options |= LHF_ZEROINIT; + + m_pFirstFreeBlock = NULL; + +@@ -1133,7 +1138,7 @@ BOOL UnlockedLoaderHeap::UnlockedReservePages(size_t dwSizeToCommit) + } + + // Commit first set of pages, since it will contain the LoaderHeapBlock +- void *pTemp = ClrVirtualAlloc(pData, dwSizeToCommit, MEM_COMMIT, m_flProtect); ++ void *pTemp = ClrVirtualAlloc(pData, dwSizeToCommit, MEM_COMMIT, (m_Options & LHF_EXECUTABLE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); + if (pTemp == NULL) + { + //_ASSERTE(!"Unable to ClrVirtualAlloc commit in a loaderheap"); +@@ -1225,7 +1230,7 @@ BOOL UnlockedLoaderHeap::GetMoreCommittedPages(size_t dwMinSize) + dwSizeToCommit = ALIGN_UP(dwSizeToCommit, GetOsPageSize()); + + // Yes, so commit the desired number of reserved pages +- void *pData = ClrVirtualAlloc(m_pPtrToEndOfCommittedRegion, dwSizeToCommit, MEM_COMMIT, m_flProtect); ++ void *pData = ClrVirtualAlloc(m_pPtrToEndOfCommittedRegion, dwSizeToCommit, MEM_COMMIT, (m_Options & LHF_EXECUTABLE) ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE); + if (pData == NULL) + return FALSE; + +@@ -1351,7 +1356,7 @@ void *UnlockedLoaderHeap::UnlockedAllocMem_NoThrow(size_t dwSize + // Don't fill the memory we allocated - it is assumed to be zeroed - fill the memory after it + memset(pAllocatedBytes + dwRequestedSize, 0xEE, LOADER_HEAP_DEBUG_BOUNDARY); + #endif +- if (dwRequestedSize > 0) ++ if ((dwRequestedSize > 0) && (m_Options & LHF_ZEROINIT)) + { + _ASSERTE_MSG(pAllocatedBytes[0] == 0 && memcmp(pAllocatedBytes, pAllocatedBytes + 1, dwRequestedSize - 1) == 0, + "LoaderHeap must return zero-initialized memory"); +@@ -1529,7 +1534,8 @@ void UnlockedLoaderHeap::UnlockedBackoutMem(void *pMem, + { + // Cool. This was the last block allocated. We can just undo the allocation instead + // of going to the freelist. +- memset(pMem, 0, dwSize); // Must zero init this memory as AllocMem expect it ++ if (m_Options & LHF_ZEROINIT) ++ memset(pMem, 0x00, dwSize); // Fill freed region with 0 + m_pAllocPtr = (BYTE*)pMem; + } + else +@@ -1639,6 +1645,7 @@ void *UnlockedLoaderHeap::UnlockedAllocAlignedMem_NoThrow(size_t dwRequestedSiz + + + ((BYTE*&)pResult) += extra; ++ + #ifdef _DEBUG + BYTE *pAllocatedBytes = (BYTE *)pResult; + #if LOADER_HEAP_DEBUG_BOUNDARY > 0 +@@ -1646,7 +1653,7 @@ void *UnlockedLoaderHeap::UnlockedAllocAlignedMem_NoThrow(size_t dwRequestedSiz + memset(pAllocatedBytes + dwRequestedSize, 0xee, LOADER_HEAP_DEBUG_BOUNDARY); + #endif + +- if (dwRequestedSize != 0) ++ if ((dwRequestedSize != 0) && (m_Options & LHF_ZEROINIT)) + { + _ASSERTE_MSG(pAllocatedBytes[0] == 0 && memcmp(pAllocatedBytes, pAllocatedBytes + 1, dwRequestedSize - 1) == 0, + "LoaderHeap must return zero-initialized memory"); +@@ -1766,6 +1773,16 @@ void *UnlockedLoaderHeap::UnlockedAllocMemForCode_NoThrow(size_t dwHeaderSize, s + + #endif // #ifndef DACCESS_COMPILE + ++BOOL UnlockedLoaderHeap::IsExecutable() ++{ ++ return (m_Options & LHF_EXECUTABLE); ++} ++ ++BOOL UnlockedLoaderHeap::IsZeroInit() ++{ ++ return (m_Options & LHF_ZEROINIT); ++} ++ + #ifdef DACCESS_COMPILE + + void UnlockedLoaderHeap::EnumMemoryRegions(CLRDataEnumMemoryFlags flags) +diff --git a/src/vm/amd64/cgenamd64.cpp b/src/vm/amd64/cgenamd64.cpp +index 497abcd502d..20dca22e36b 100644 +--- a/src/vm/amd64/cgenamd64.cpp ++++ b/src/vm/amd64/cgenamd64.cpp +@@ -670,6 +670,19 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam) + _ASSERTE(DbgIsExecutable(&m_movR10[0], &m_jmpRAX[3]-&m_movR10[0])); + } + ++void UMEntryThunkCode::Poison() ++{ ++ CONTRACTL ++ { ++ NOTHROW; ++ GC_NOTRIGGER; ++ MODE_ANY; ++ } ++ CONTRACTL_END; ++ ++ m_movR10[0] = X86_INSTR_INT3; ++} ++ + UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback) + { + LIMITED_METHOD_CONTRACT; +diff --git a/src/vm/amd64/cgencpu.h b/src/vm/amd64/cgencpu.h +index 64a6501dc0e..b74e3ca7d3e 100644 +--- a/src/vm/amd64/cgencpu.h ++++ b/src/vm/amd64/cgencpu.h +@@ -472,6 +472,7 @@ struct DECLSPEC_ALIGN(8) UMEntryThunkCode + BYTE m_padding2[5]; + + void Encode(BYTE* pTargetCode, void* pvSecretParam); ++ void Poison(); + + LPCBYTE GetEntryPoint() const + { +diff --git a/src/vm/arm/cgencpu.h b/src/vm/arm/cgencpu.h +index 181d5f10eb9..6f128f65345 100644 +--- a/src/vm/arm/cgencpu.h ++++ b/src/vm/arm/cgencpu.h +@@ -988,6 +988,7 @@ struct DECLSPEC_ALIGN(4) UMEntryThunkCode + TADDR m_pvSecretParam; + + void Encode(BYTE* pTargetCode, void* pvSecretParam); ++ void Poison(); + + LPCBYTE GetEntryPoint() const + { +diff --git a/src/vm/arm/stubs.cpp b/src/vm/arm/stubs.cpp +index 2e8bb19d499..39b5937129a 100644 +--- a/src/vm/arm/stubs.cpp ++++ b/src/vm/arm/stubs.cpp +@@ -2522,6 +2522,12 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam) + FlushInstructionCache(GetCurrentProcess(),&m_code,sizeof(m_code)); + } + ++void UMEntryThunkCode::Poison() ++{ ++ // Insert 'bkpt 0x00be' at the entry point ++ m_code[0] = 0xbebe; ++} ++ + ///////////////////////////// UNIMPLEMENTED ////////////////////////////////// + + #ifndef DACCESS_COMPILE +diff --git a/src/vm/arm64/cgencpu.h b/src/vm/arm64/cgencpu.h +index d8bbcf7d1d6..5c522c57351 100644 +--- a/src/vm/arm64/cgencpu.h ++++ b/src/vm/arm64/cgencpu.h +@@ -481,6 +481,7 @@ struct DECLSPEC_ALIGN(16) UMEntryThunkCode + TADDR m_pvSecretParam; + + void Encode(BYTE* pTargetCode, void* pvSecretParam); ++ void Poison(); + + LPCBYTE GetEntryPoint() const + { +diff --git a/src/vm/arm64/stubs.cpp b/src/vm/arm64/stubs.cpp +index 40d274959f8..df2124db448 100644 +--- a/src/vm/arm64/stubs.cpp ++++ b/src/vm/arm64/stubs.cpp +@@ -1244,6 +1244,10 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam) + FlushInstructionCache(GetCurrentProcess(),&m_code,sizeof(m_code)); + } + ++void UMEntryThunkCode::Poison() ++{ ++ ++} + + #ifdef PROFILING_SUPPORTED + #include "proftoeeinterfaceimpl.h" +diff --git a/src/vm/dllimportcallback.cpp b/src/vm/dllimportcallback.cpp +index 90c01a496bc..8684c12167b 100644 +--- a/src/vm/dllimportcallback.cpp ++++ b/src/vm/dllimportcallback.cpp +@@ -1111,13 +1111,8 @@ UMEntryThunk* UMEntryThunk::CreateUMEntryThunk() + + UMEntryThunk * p; + +-#ifdef FEATURE_WINDOWSPHONE + // On the phone, use loader heap to save memory commit of regular executable heap + p = (UMEntryThunk *)(void *)SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->AllocMem(S_SIZE_T(sizeof(UMEntryThunk))); +-#else +- p = new (executable) UMEntryThunk; +- memset (p, 0, sizeof(*p)); +-#endif + + RETURN p; + } +@@ -1126,11 +1121,10 @@ void UMEntryThunk::Terminate() + { + WRAPPER_NO_CONTRACT; + +-#ifdef FEATURE_WINDOWSPHONE ++ _ASSERTE(!SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->IsZeroInit()); ++ m_code.Poison(); ++ + SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->BackoutMem(this, sizeof(UMEntryThunk)); +-#else +- DeleteExecutable(this); +-#endif + } + + VOID UMEntryThunk::FreeUMEntryThunk(UMEntryThunk* p) +diff --git a/src/vm/dllimportcallback.h b/src/vm/dllimportcallback.h +index af2a0b1d927..e79c5f03ef9 100644 +--- a/src/vm/dllimportcallback.h ++++ b/src/vm/dllimportcallback.h +@@ -326,10 +326,6 @@ class UMEntryThunk + { + DestroyLongWeakHandle(GetObjectHandle()); + } +- +-#ifdef _DEBUG +- FillMemory(this, sizeof(*this), 0xcc); +-#endif + } + + void Terminate(); +diff --git a/src/vm/i386/cgencpu.h b/src/vm/i386/cgencpu.h +index ff76d992fc2..e4a623b715c 100644 +--- a/src/vm/i386/cgencpu.h ++++ b/src/vm/i386/cgencpu.h +@@ -504,6 +504,7 @@ struct DECLSPEC_ALIGN(4) UMEntryThunkCode + const BYTE * m_execstub; // pointer to destination code // make sure the backpatched portion is dword aligned. + + void Encode(BYTE* pTargetCode, void* pvSecretParam); ++ void Poison(); + + LPCBYTE GetEntryPoint() const + { +diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp +index c75490babdf..e315ffb1e6e 100644 +--- a/src/vm/i386/cgenx86.cpp ++++ b/src/vm/i386/cgenx86.cpp +@@ -1588,6 +1588,13 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam) + FlushInstructionCache(GetCurrentProcess(),GetEntryPoint(),sizeof(UMEntryThunkCode)); + } + ++void UMEntryThunkCode::Poison() ++{ ++ LIMITED_METHOD_CONTRACT; ++ ++ m_movEAX = X86_INSTR_INT3; ++} ++ + UMEntryThunk* UMEntryThunk::Decode(LPVOID pCallback) + { + LIMITED_METHOD_CONTRACT; +diff --git a/src/vm/loaderallocator.cpp b/src/vm/loaderallocator.cpp +index 1a05bf2c059..ff54277efdc 100644 +--- a/src/vm/loaderallocator.cpp ++++ b/src/vm/loaderallocator.cpp +@@ -1005,7 +1005,9 @@ void LoaderAllocator::Init(BaseDomain *pDomain, BYTE *pExecutableHeapMemory) + dwExecutableHeapReserveSize, + LOADERHEAP_PROFILE_COUNTER, + NULL, +- TRUE /* Make heap executable */); ++ TRUE /* Make heap executable */, ++ FALSE /* Disable zero-initialization (needed by UMEntryThunkCode::Poison) */ ++ ); + initReservedMem += dwExecutableHeapReserveSize; + } + + + diff --git a/packaging/poison2.patch b/packaging/poison2.patch new file mode 100644 index 0000000000..b2f985bd69 --- /dev/null +++ b/packaging/poison2.patch @@ -0,0 +1,25 @@ +From 81df4e81eb51a01f9ba583cd77acf3bac6e6e77e Mon Sep 17 00:00:00 2001 +From: Jonghyun Park +Date: Wed, 2 Aug 2017 14:11:26 +0900 +Subject: [PATCH] Use 'udf 0xff' instead of 'bkpt 0xbe' as a poison (#13152) + +--- + src/vm/arm/stubs.cpp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/vm/arm/stubs.cpp b/src/vm/arm/stubs.cpp +index 39b5937129a..05ffed49da7 100644 +--- a/src/vm/arm/stubs.cpp ++++ b/src/vm/arm/stubs.cpp +@@ -2524,8 +2524,8 @@ void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam) + + void UMEntryThunkCode::Poison() + { +- // Insert 'bkpt 0x00be' at the entry point +- m_code[0] = 0xbebe; ++ // Insert 'udf 0xff' at the entry point ++ m_code[0] = 0xdeff; + } + + ///////////////////////////// UNIMPLEMENTED ////////////////////////////////// + -- cgit v1.2.3