diff options
author | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2019-07-04 16:36:03 +0300 |
---|---|---|
committer | Vyacheslav Cherkashin <v.cherkashin@samsung.com> | 2019-07-17 16:48:55 +0300 |
commit | b307e01209cb82bb4067649a338e1bba8ab71efe (patch) | |
tree | a974b3f3412b5154b61e0e6d9bd50a888d286e80 /src | |
parent | 132e1ad7f68d5eb3a71ad7b1e5d63109188dbd09 (diff) | |
download | coreclr-b307e01209cb82bb4067649a338e1bba8ab71efe.tar.gz coreclr-b307e01209cb82bb4067649a338e1bba8ab71efe.tar.bz2 coreclr-b307e01209cb82bb4067649a338e1bba8ab71efe.zip |
Add ASan wrapper for extern external calls (AMD64)
Signed-off-by: Vyacheslav Cherkashin <v.cherkashin@samsung.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/vm/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/vm/amd64/asan_wrapper.S | 127 | ||||
-rw-r--r-- | src/vm/dllimport.cpp | 86 |
3 files changed, 214 insertions, 0 deletions
diff --git a/src/vm/CMakeLists.txt b/src/vm/CMakeLists.txt index 62acecf11e..ff514730c5 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 0000000000..a58828b2d3 --- /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 18e77d8490..76ca654622 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) { |