summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2019-07-22 13:40:47 +0300
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>2019-08-21 17:09:48 +0300
commitd5d6263f30af89beb4e50359cae3d280b11580bb (patch)
tree5d0eadd3f0514a049d487586ccdd15d5561cf9d8
parenteed0dbb16a77fed48ea397d140e58611b1e7efd2 (diff)
downloadcoreclr-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.txt13
-rw-r--r--src/vm/arm/stubs.cpp10
-rw-r--r--src/vm/arm/tizenasanenv.S61
-rw-r--r--src/vm/dllimport.cpp13
-rw-r--r--src/vm/tizenasanenv.cpp135
-rw-r--r--src/vm/tizenasanenv.h15
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_