diff options
author | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2019-07-22 13:40:47 +0300 |
---|---|---|
committer | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2019-08-21 17:09:48 +0300 |
commit | d5d6263f30af89beb4e50359cae3d280b11580bb (patch) | |
tree | 5d0eadd3f0514a049d487586ccdd15d5561cf9d8 | |
parent | eed0dbb16a77fed48ea397d140e58611b1e7efd2 (diff) | |
download | coreclr-d5d6263f30af89beb4e50359cae3d280b11580bb.tar.gz coreclr-d5d6263f30af89beb4e50359cae3d280b11580bb.tar.bz2 coreclr-d5d6263f30af89beb4e50359cae3d280b11580bb.zip |
[Tizen] Implement ASan wrapper for Linux ARM32
This commit implements wrappers that allow interception transitions
from managed to external unmanaged code (CIL -> native) and back
(native -> CIL). This allows enable/disable ASan during transitions.
Due to this, we sanitize only external code, which allows us to
achieve acceptable performance.
Change-Id: I53ecdc14d28f7210cd9e7f5bd4db0c8ef5ed81fc
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r-- | src/vm/CMakeLists.txt | 13 | ||||
-rw-r--r-- | src/vm/arm/stubs.cpp | 10 | ||||
-rw-r--r-- | src/vm/arm/tizenasanenv.S | 61 | ||||
-rw-r--r-- | src/vm/dllimport.cpp | 13 | ||||
-rw-r--r-- | src/vm/tizenasanenv.cpp | 135 | ||||
-rw-r--r-- | src/vm/tizenasanenv.h | 15 |
6 files changed, 247 insertions, 0 deletions
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index 9bdbee3c0e..a130160413 100644 --- a/src/vm/CMakeLists.txt +++ b/src/vm/CMakeLists.txt @@ -714,6 +714,14 @@ elseif(CLR_CMAKE_TARGET_ARCH_ARM64) endif() else(WIN32) + if (TIZEN_ASAN_ENVIRONMENT) + list(APPEND VM_SOURCES_WKS + tizenasanenv.cpp + ) + list(APPEND VM_HEADERS_WKS + tizenasanenv.h + ) + endif() if(CLR_CMAKE_TARGET_ARCH_AMD64) set(VM_SOURCES_WKS_ARCH_ASM @@ -750,6 +758,11 @@ else(WIN32) ${ARCH_SOURCES_DIR}/patchedcode.S ${ARCH_SOURCES_DIR}/pinvokestubs.S ) + if (TIZEN_ASAN_ENVIRONMENT) + list(APPEND VM_SOURCES_WKS_ARCH_ASM + ${ARCH_SOURCES_DIR}/tizenasanenv.S + ) + endif() elseif(CLR_CMAKE_TARGET_ARCH_ARM64) set(VM_SOURCES_WKS_ARCH_ASM ${ARCH_SOURCES_DIR}/asmhelpers.S diff --git a/src/vm/arm/stubs.cpp b/src/vm/arm/stubs.cpp index 7e7435c107..b86732c424 100644 --- a/src/vm/arm/stubs.cpp +++ b/src/vm/arm/stubs.cpp @@ -26,6 +26,10 @@ #include "ecall.h" #include "threadsuspend.h" +#if defined(TIZEN_ASAN_ENVIRONMENT) && !defined(CROSS_COMPILE) && !defined(DACCESS_COMPILE) +#include <tizenasanenv.h> +#endif + // target write barriers EXTERN_C void JIT_WriteBarrier(Object **dst, Object *ref); EXTERN_C void JIT_WriteBarrier_End(); @@ -2477,6 +2481,12 @@ class UMEntryThunk * UMEntryThunk::Decode(void *pCallback) void UMEntryThunkCode::Encode(BYTE* pTargetCode, void* pvSecretParam) { +#if defined(TIZEN_ASAN_ENVIRONMENT) && !defined(CROSS_COMPILE) && !defined(DACCESS_COMPILE) + pTargetCode = (BYTE *)TizenASanEnv::CreateWrapper((LPVOID)pTargetCode, + TizenASanEnv::PushAndDisableASan, + TizenASanEnv::PopAndEnableASan); +#endif + // ldr r12, [pc + 8] m_code[0] = 0xf8df; m_code[1] = 0xc008; diff --git a/src/vm/arm/tizenasanenv.S b/src/vm/arm/tizenasanenv.S new file mode 100644 index 0000000000..6a8adb94fe --- /dev/null +++ b/src/vm/arm/tizenasanenv.S @@ -0,0 +1,61 @@ +.macro PUSH_REGS + push {r0-r12} + vpush.64 {d0-d7} +.endm + +.macro POP_REGS + vpop.64 {d0-d7} + pop {r0-r12} +.endm + + +// Export symbols +.global tizenASanWrapper +.global tizenASanWrapperSize +.global tizenASanWrapperEntryOffset + +.text +.arm + +tizenASanWrapper: +// !!! ATTENTION !!! +// Don't move this labels (target, pushAddr, popAddr) +// because they mapped to AuxiliaryCalls struct from src/vm/tizenasanenv.cpp +target: .word 0xdeadc0de +pushAddr: .word 0xdeadc0de @ void pushAddr(LPVOID addr) +popAddr: .word 0xdeadc0de @ LPVOID popAddr() + +entryPointer: + // Save context + PUSH_REGS + + // Save the return address and call 'pre handler' + mov r0, lr + ldr r1, pushAddr + blx r1 + + // Restore context + POP_REGS + + // Change the return address + adr lr, postLabel + + // Call original function + ldr pc, target +postLabel: + // Save context + PUSH_REGS + + // Get the return address and call 'post handler' + ldr r0, popAddr + blx r0 + + // Restore the return address + mov lr, r0 + + // Restore context + POP_REGS + bx lr + +tizenASanWrapperSize: .word . - tizenASanWrapper +tizenASanWrapperEntryOffset: .word entryPointer - tizenASanWrapper diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp index eed690454d..2ee15f675d 100644 --- a/src/vm/dllimport.cpp +++ b/src/vm/dllimport.cpp @@ -46,6 +46,10 @@ #include "compile.h" #endif // FEATURE_PREJIT +#ifdef TIZEN_ASAN_ENVIRONMENT +#include <tizenasanenv.h> +#endif // TIZEN_ASAN_ENVIRONMENT + #include "eventtrace.h" #include "clr/fs/path.h" using namespace clr::fs; @@ -6696,6 +6700,15 @@ VOID NDirect::NDirectLink(NDirectMethodDesc *pMD) LPVOID pvTarget = NDirectGetEntryPoint(pMD, hmod); if (pvTarget) { +#ifdef TIZEN_ASAN_ENVIRONMENT + if (PAL_IsSanitizedLibraryDirect(hmod)) + { + pvTarget = TizenASanEnv::CreateWrapper(pvTarget, + TizenASanEnv::PushAndEnableASan, + TizenASanEnv::PopAndDisableASan); + } +#endif // TIZEN_ASAN_ENVIRONMENT + pMD->SetNDirectTarget(pvTarget); fSuccess = TRUE; } diff --git a/src/vm/tizenasanenv.cpp b/src/vm/tizenasanenv.cpp new file mode 100644 index 0000000000..ddb2b0e451 --- /dev/null +++ b/src/vm/tizenasanenv.cpp @@ -0,0 +1,135 @@ +#include <string.h> +#include "common.h" +#include "tizenasanenv.h" + + +template <typename Type, int STACK_SIZE> +class StaticStack { + // We don't create constructor because + // this class is used in a zeroed memory area +public: + void push(Type addr) + { + _ASSERTE(m_pos < STACK_SIZE); + + m_data[m_pos++] = addr; + } + + void pop() + { + _ASSERTE(m_pos > 0); + --m_pos; + } + + Type top() + { + _ASSERTE(m_pos > 0); + + return m_data[m_pos - 1]; + } + + bool empty() + { + return m_pos == 0; + } + +private: + int m_pos; + Type m_data[STACK_SIZE]; +}; + +#include <pshpack1.h> +struct AuxiliaryCalls { + LPVOID target; + void (*pushAddr)(LPVOID addr); + LPVOID (*popAddr)(); +}; + +extern "C" void __sanitizer_disable_interceptors(); +extern "C" void __sanitizer_enable_interceptors(); + +extern LPVOID tizenASanWrapper; +extern UINT32 tizenASanWrapperSize; +extern UINT32 tizenASanWrapperEntryOffset; + +static __thread StaticStack<LPVOID, 128> s_retaddrStack; +static __thread int s_enableCounter; + + +static void TryEnable() +{ + if (s_enableCounter == 0) + __sanitizer_enable_interceptors(); + ++s_enableCounter; +} + +static void TryDisable() +{ + if (s_enableCounter == 1) + __sanitizer_disable_interceptors(); + --s_enableCounter; +} + + +namespace TizenASanEnv { + +void PushAndDisableASan(LPVOID addr) +{ + TryDisable(); + s_retaddrStack.push(addr); +} + +LPVOID PopAndEnableASan() +{ + LPVOID addr = s_retaddrStack.top(); + s_retaddrStack.pop(); + + TryEnable(); + + return addr; +} + +void PushAndEnableASan(LPVOID addr) +{ + s_retaddrStack.push(addr); + TryEnable(); +} + +LPVOID PopAndDisableASan() +{ + TryDisable(); + + LPVOID addr = s_retaddrStack.top(); + s_retaddrStack.pop(); + + return addr; +} + +LPVOID CreateWrapper(LPVOID target, void (*pushAddr)(LPVOID addr), LPVOID (*popAddr)()) +{ + _ASSERTE(tizenASanWrapperEntryOffset == sizeof(AuxiliaryCalls)); + + LPVOID wrapperSpace = (LPVOID)SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->AllocMem(S_SIZE_T(tizenASanWrapperSize)); + + AuxiliaryCalls calls = { + .target = target, + .pushAddr = pushAddr, + .popAddr = popAddr, + }; + + // copy auxiliary calls + memcpy(wrapperSpace, &calls, sizeof(calls)); + + LPVOID entryPointer = (LPVOID)((UINT_PTR)wrapperSpace + tizenASanWrapperEntryOffset); + LPVOID wrapperEntryPointer = (LPVOID)((UINT_PTR)&tizenASanWrapper + tizenASanWrapperEntryOffset); + UINT32 wrapperCodeSize = tizenASanWrapperSize - tizenASanWrapperEntryOffset; + + // copy executable code wrapper + memcpy(entryPointer, wrapperEntryPointer, wrapperCodeSize); + + FlushInstructionCache(GetCurrentProcess(), wrapperSpace, tizenASanWrapperSize); + + return entryPointer; +} + +} // namespace TizenASanEnv diff --git a/src/vm/tizenasanenv.h b/src/vm/tizenasanenv.h new file mode 100644 index 0000000000..7200936d16 --- /dev/null +++ b/src/vm/tizenasanenv.h @@ -0,0 +1,15 @@ +#ifndef TIZENASANENV_H_ +#define TIZENASANENV_H_ + +namespace TizenASanEnv { + +void PushAndDisableASan(LPVOID addr); +LPVOID PopAndEnableASan(); +void PushAndEnableASan(LPVOID addr); +LPVOID PopAndDisableASan(); + +LPVOID CreateWrapper(LPVOID target, void (*pushAddr)(LPVOID addr), LPVOID (*popAddr)()); + +} // namespace TizenASanEnv + +#endif // TIZENASANENV_H_ |