summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVyacheslav Cherkashin <v.cherkashin@samsung.com>2019-07-04 13:36:03 (GMT)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>2019-07-17 13:48:55 (GMT)
commitb307e01209cb82bb4067649a338e1bba8ab71efe (patch)
treea974b3f3412b5154b61e0e6d9bd50a888d286e80
parent132e1ad7f68d5eb3a71ad7b1e5d63109188dbd09 (diff)
downloadcoreclr-b307e01209cb82bb4067649a338e1bba8ab71efe.zip
coreclr-b307e01209cb82bb4067649a338e1bba8ab71efe.tar.gz
coreclr-b307e01209cb82bb4067649a338e1bba8ab71efe.tar.bz2
Add ASan wrapper for extern external calls (AMD64)
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
-rw-r--r--src/vm/CMakeLists.txt1
-rw-r--r--src/vm/amd64/asan_wrapper.S127
-rw-r--r--src/vm/dllimport.cpp86
3 files changed, 214 insertions, 0 deletions
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt
index 62acecf..ff51473 100644
--- a/src/vm/CMakeLists.txt
+++ b/src/vm/CMakeLists.txt
@@ -718,6 +718,7 @@ else(WIN32)
${ARCH_SOURCES_DIR}/unixasmhelpers.S
${ARCH_SOURCES_DIR}/umthunkstub.S
${ARCH_SOURCES_DIR}/virtualcallstubamd64.S
+ ${ARCH_SOURCES_DIR}/asan_wrapper.S
)
elseif(CLR_CMAKE_TARGET_ARCH_I386)
set(VM_SOURCES_WKS_ARCH_ASM
diff --git a/src/vm/amd64/asan_wrapper.S b/src/vm/amd64/asan_wrapper.S
new file mode 100644
index 0000000..a58828b
--- /dev/null
+++ b/src/vm/amd64/asan_wrapper.S
@@ -0,0 +1,127 @@
+# ----------------------------------------------------------------------------------------
+# Writes "Hello, World" to the console using only system calls. Runs on 64-bit Linux only.
+# To assemble and run:
+#
+# gcc -c hello.s && ld hello.o && ./a.out
+#
+# or
+#
+# gcc -nostdlib -no-pie hello.s && ./a.out
+# ----------------------------------------------------------------------------------------
+
+RETADDR_OFFSET=8*15
+
+.macro PUSH_REGS
+ push %rdi # 0, arg0
+ push %rsi # 1, arg1
+ push %rdx # 2, arg2
+ push %rcx # 3, arg3
+ push %r8 # 4, arg4
+ push %r9 # 5, arg5
+ push %r10 # 6, ...
+ push %r11 # 7, temprory reg
+ push %rax # 8
+
+ push %rbp
+ push %rbx
+ push %r15
+ push %r14
+ push %r13
+ push %r12
+.endm
+
+.macro POP_REGS
+ pop %r12
+ pop %r13
+ pop %r14
+ pop %r15
+ pop %rbx
+ pop %rbp
+
+
+ pop %rax
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rcx
+ pop %rdx
+ pop %rsi
+ pop %rdi
+.endm
+
+ .global hex_wrapper
+ .global hex_wrapper_size
+ .global hex_wrapper_entry_offset
+
+ # Extern functions
+ .global asan_enable_addr_offset
+ .global asan_disable_addr_offset
+ .global target_addr_offset
+ .global get_return_addr_offset
+
+
+ .text
+ .code64
+
+hex_wrapper:
+asan_enable_addr: .quad 0x0badc0de0badc0de
+asan_disable_addr: .quad 0x0badc0de0badc0de
+target_addr: .quad 0x0badc0de0badc0de
+get_return_addr: .quad 0x0badc0de0badc0de
+
+hex_wrapper_entry:
+ # Save context
+ PUSH_REGS
+
+ # Save the return adderss
+ call *get_return_addr(%rip) # rax: get space for saving the return address
+ mov RETADDR_OFFSET(%rsp), %rdi # rdi: get return address
+ mov %rdi, (%rax) # save the return address to the received space
+
+ # Change the return address on the 'wrapper_second'
+ call next
+next: pop %rax # rax: get current rip
+ add $(wrapper_second - next), %rax # rax: add offset to 'wrapper_second'
+ mov %rax, RETADDR_OFFSET(%rsp) # change the return address
+
+ # Enable ASan
+ call *asan_enable_addr(%rip)
+
+ # Restore context
+ POP_REGS
+
+ # Call original function
+ jmp *target_addr(%rip)
+wrapper_second:
+ # Save context
+ PUSH_REGS
+
+ # Align stack
+ add $8, %rsp
+
+ # Disable ASan
+ call *asan_disable_addr(%rip)
+
+ # Restore the return address
+ call *get_return_addr(%rip) # rax: get pointer to saved the return address
+ sub $8, %rsp # 'restore' aligned stack
+ mov (%rax), %rdi # rdi: get the return address
+ mov %rdi, RETADDR_OFFSET(%rsp) # restore the return address
+
+ # Restore context
+ POP_REGS
+
+ # Return
+ ret
+
+hex_wrapper_size: .quad . - hex_wrapper
+
+hex_wrapper_entry_offset: .quad hex_wrapper_entry - hex_wrapper
+asan_enable_addr_offset: .quad asan_enable_addr - hex_wrapper
+asan_disable_addr_offset: .quad asan_disable_addr - hex_wrapper
+target_addr_offset: .quad target_addr - hex_wrapper
+get_return_addr_offset: .quad get_return_addr - hex_wrapper
+
+
+# set environment LD_PRELOAD /root/asan/libasan.so
diff --git a/src/vm/dllimport.cpp b/src/vm/dllimport.cpp
index 18e77d8..76ca654 100644
--- a/src/vm/dllimport.cpp
+++ b/src/vm/dllimport.cpp
@@ -6850,6 +6850,73 @@ HINSTANCE NDirect::LoadLibraryModule(NDirectMethodDesc * pMD, LoadLibErrorTracke
return hmod.Extract();
}
+
+extern "C" void __sanitizer_enable_calls_forwarding();
+extern "C" void __sanitizer_disable_calls_forwarding();
+
+
+extern "C" long write(int fd, const void *buf, int count);
+
+void my_enable()
+{
+ char msg[] = "#### MY_ENABLE\n";
+ write(1, msg, sizeof(msg) - 1);
+ __sanitizer_disable_calls_forwarding();
+}
+
+void my_disable()
+{
+ __sanitizer_enable_calls_forwarding();
+ char msg[] = "#### MY_DISABLE\n";
+ write(1, msg, sizeof(msg) - 1);
+}
+
+#include <pshpack1.h>
+struct my_struct {
+ void (*asan_enable)();
+ void (*asan_disable)();
+ UINT64 real_func;
+ UINT64 *(*get_addr_space)();
+};
+
+
+static __thread UINT64 g_addr_space;
+UINT64 *get_return_addr_space()
+{
+ return &g_addr_space;
+}
+
+extern UINT64 hex_wrapper;
+extern UINT64 hex_wrapper_size;
+extern UINT64 hex_wrapper_entry_offset;
+
+
+LPVOID ASanCreateWraper(LPVOID target)
+{
+ void *wrapper_space = (void *)SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()->AllocMem(S_SIZE_T(0x200));
+
+ // copy asan_wrapper
+ memcpy(wrapper_space, &hex_wrapper, hex_wrapper_size);
+
+ struct my_struct pp = {
+ .asan_enable = my_enable,
+ .asan_disable = my_disable,
+ .real_func = (UINT64)target,
+ .get_addr_space = get_return_addr_space,
+ };
+
+ // copy my_struct
+ memcpy(wrapper_space, &pp, sizeof(pp));
+
+ return (LPVOID)((UINT64)wrapper_space + hex_wrapper_entry_offset);
+}
+
+
+extern "C" int dprintf(int fd, const char *format, ...);
+extern "C" void *dlopen(const char *filename, int flags);
+extern "C" int dlclose(void *handle);
+extern "C" void *dlsym(void *handle, const char *symbol);
+
//---------------------------------------------------------
// Loads the DLL and finds the procaddress for an N/Direct call.
//---------------------------------------------------------
@@ -6901,6 +6968,25 @@ VOID NDirect::NDirectLink(NDirectMethodDesc *pMD)
if ( hmod )
{
LPVOID pvTarget = NDirectGetEntryPoint(pMD, hmod);
+ dprintf(1, "#### NDirect::NDirectLink: [POINTER TO FUNCTION] pMD=%p size=%d HasNonVtableSlot[%d %p] pvTarget=%p entry_name=%s lib_name='%s' IsComPlusCall=%d IsGenericComPlusCall=%d\n",
+ pMD, pMD->SizeOf(),
+ pMD->HasNonVtableSlot(),
+ NULL, //pMD->HasNonVtableSlot() ? ((RelativePointer<PCODE> *)pMD->GetAddrOfHasNonVtableSlot())->GetValueMaybeNull() : NULL,
+ pvTarget, pMD->GetEntrypointName(), pMD->GetLibName(), pMD->IsComPlusCall(), pMD->IsGenericComPlusCall());
+ if (1) {
+ bool is_asan_lib = false;
+ void *h = dlopen(pMD->GetLibName(), 0x00001 /* RTLD_LAZY */);
+ if (h) {
+ is_asan_lib = !!dlsym(h, "__asan_init");
+ dlclose(h);
+ }
+ dprintf(1, "#### h=%p IS_ASAN_LIB=%d pMD->GetLibName()=%s\n", h, is_asan_lib, pMD->GetLibName());
+ is_asan_lib = !!h;
+ if (is_asan_lib) {
+ dprintf(1, "#### NDirect::NDirectLink: CHANGE pvTarget\n");
+ pvTarget = ASanCreateWraper(pvTarget);
+ }
+ }
if (pvTarget)
{