summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Drobyshev <a.drobyshev@samsung.com>2019-07-16 12:23:18 (GMT)
committerVyacheslav Cherkashin <v.cherkashin@samsung.com>2019-07-26 10:54:06 (GMT)
commitad1d0aa305e2ada610745accee6abf1972423508 (patch)
tree13ef9336d2eed44320cccdb2b383f7a2ea8f0bbf
parent59075187072252b2f048d2b4616f3f86960a2be6 (diff)
downloadcoreclr-ad1d0aa305e2ada610745accee6abf1972423508.zip
coreclr-ad1d0aa305e2ada610745accee6abf1972423508.tar.gz
coreclr-ad1d0aa305e2ada610745accee6abf1972423508.tar.bz2
[Tizen] Implement detecting of sanitized libraries
Parse ".dynamic" section (ELF dynamic array tags) of the module being added, find ".rel(a).plt" section and search it for presence of '__asan_init' symbol. Change-Id: Ie7cc4c818b791b5f00713b42ba15131325b8152c Signed-off-by: Andrey Drobyshev <a.drobyshev@samsung.com>
-rw-r--r--src/pal/inc/pal.h8
-rw-r--r--src/pal/src/CMakeLists.txt6
-rw-r--r--src/pal/src/include/pal/module.h4
-rw-r--r--src/pal/src/loader/module.cpp23
-rw-r--r--src/pal/src/loader/tizenasanenvmodule.cpp133
-rw-r--r--src/pal/src/loader/tizenasanenvmodule.h8
6 files changed, 182 insertions, 0 deletions
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index 76e04cd..45364c9 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -490,6 +490,14 @@ PALAPI
PAL_UnregisterModule(
IN HINSTANCE hInstance);
+#ifdef TIZEN_ASAN_ENVIRONMENT
+PALIMPORT
+BOOL
+PALAPI
+PAL_IsSanitizedModule(
+ IN HINSTANCE hInstance);
+#endif
+
PALIMPORT
BOOL
PALAPI
diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt
index 8e69ee9..7a927f4 100644
--- a/src/pal/src/CMakeLists.txt
+++ b/src/pal/src/CMakeLists.txt
@@ -281,6 +281,12 @@ set(SOURCES
thread/tls.cpp
)
+if (TIZEN_ASAN_ENVIRONMENT)
+ list(APPEND SOURCES
+ loader/tizenasanenvmodule.cpp
+ )
+endif()
+
if(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND)
set(LIBUNWIND_OBJECTS $<TARGET_OBJECTS:libunwind>)
endif(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND)
diff --git a/src/pal/src/include/pal/module.h b/src/pal/src/include/pal/module.h
index aacc326..d2ee88f 100644
--- a/src/pal/src/include/pal/module.h
+++ b/src/pal/src/include/pal/module.h
@@ -39,6 +39,10 @@ typedef struct _MODSTRUCT
/* -1 means infinite reference count - module is never released */
BOOL threadLibCalls; /* TRUE for DLL_THREAD_ATTACH/DETACH notifications enabled, FALSE if they are disabled */
+#ifdef TIZEN_ASAN_ENVIRONMENT
+ BOOL is_sanitized;
+#endif
+
#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN
ino_t inode;
dev_t device;
diff --git a/src/pal/src/loader/module.cpp b/src/pal/src/loader/module.cpp
index e39cd6e..4dc06d0 100644
--- a/src/pal/src/loader/module.cpp
+++ b/src/pal/src/loader/module.cpp
@@ -60,6 +60,10 @@ SET_DEFAULT_DEBUG_CHANNEL(LOADER); // some headers have code with asserts, so do
#include <gnu/lib-names.h>
#endif
+#ifdef TIZEN_ASAN_ENVIRONMENT
+#include "tizenasanenvmodule.h"
+#endif // TIZEN_ASAN_ENVIRONMENT
+
using namespace CorUnix;
// In safemath.h, Template SafeInt uses macro _ASSERTE, which need to use variable
@@ -802,6 +806,17 @@ PAL_UnregisterModule(
PERF_EXIT(PAL_UnregisterModule);
}
+#ifdef TIZEN_ASAN_ENVIRONMENT
+PALIMPORT
+BOOL
+PALAPI
+PAL_IsSanitizedModule(
+ IN HINSTANCE hInstance)
+{
+ return ((MODSTRUCT *)hInstance)->is_sanitized;
+}
+#endif // TIZEN_ASAN_ENVIRONMENT
+
/*++
PAL_LOADLoadPEFile
@@ -1548,6 +1563,10 @@ static MODSTRUCT *LOADAllocModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR name)
#else // NEED_DLCOMPAT
module->refcount = 1;
#endif // NEED_DLCOMPAT
+
+#ifdef TIZEN_ASAN_ENVIRONMENT
+ module->is_sanitized = FALSE;
+#endif // TIZEN_ASAN_ENVIRONMENT
module->self = module;
module->hinstance = nullptr;
module->threadLibCalls = TRUE;
@@ -1622,6 +1641,10 @@ static MODSTRUCT *LOADAddModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryN
exe_module.prev->next = module;
exe_module.prev = module;
+#ifdef TIZEN_ASAN_ENVIRONMENT
+ module->is_sanitized = module_is_sanitized(dl_handle);
+#endif // TIZEN_ASAN_ENVIRONMENT
+
#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN
module->inode = stat_buf.st_ino;
module->device = stat_buf.st_dev;
diff --git a/src/pal/src/loader/tizenasanenvmodule.cpp b/src/pal/src/loader/tizenasanenvmodule.cpp
new file mode 100644
index 0000000..9c08c5e
--- /dev/null
+++ b/src/pal/src/loader/tizenasanenvmodule.cpp
@@ -0,0 +1,133 @@
+#include <string.h>
+#include "pal.h"
+#include "llvm/ELF.h"
+#include "tizenasanenvmodule.h"
+
+#include <bits/wordsize.h>
+
+#define __ELF_WORD_SIZE __WORDSIZE
+
+#define __ELF_CONCAT1(x,y) x ## y
+#define __ELF_CONCAT(x,y) __ELF_CONCAT1(x,y)
+
+#define __ElfN(x) __ELF_CONCAT(__ELF_CONCAT( \
+ __ELF_CONCAT(Elf,__ELF_WORD_SIZE), \
+ _), \
+ x)
+#define __ElfType(x) typedef __ElfN(x) __ELF_CONCAT(Elf_,x)
+
+/*
+ * Request arguments for dlinfo().
+ */
+#define RTLD_DI_LINKMAP 2 /* Obtain link map. */
+
+struct link_map {
+ __ElfN(Addr) l_addr; /* Base Address of library */
+ const char *l_name; /* Absolute Path to Library */
+ __ElfN(Dyn) *l_ld; /* Pointer to .dynamic in memory */
+ struct link_map *l_next, *l_prev; /* linked list of of mapped libs */
+};
+
+extern "C" int dlinfo(void *handle, int request, void *info);
+
+
+struct plt_sym_resolver {
+ void *dl_handle;
+ struct link_map *lm;
+ __ElfN(Dyn) *dynamic; // .dynamic section
+ __ElfN(Sym) *dynsym; // .dynsym section
+ char *dynstr; // .dynstr section
+ long reltype; // relocation type
+ size_t pltrel_size; // size of .rel(a).plt section
+ void *jmprel; // .rel(a).plt section. Exact relocation
+ // type is resolved at runtime
+
+ plt_sym_resolver(void *handle)
+ : dl_handle(handle), lm(nullptr), dynamic(nullptr), dynsym(nullptr),
+ dynstr(nullptr), reltype(-1), pltrel_size(0), jmprel(nullptr)
+ {
+ if (handle == nullptr ||
+ dlinfo(handle, RTLD_DI_LINKMAP, &lm) < 0 ||
+ lm == nullptr)
+ return;
+ dynamic = lm->l_ld;
+ }
+
+ void walk_dynamic_section()
+ {
+ if (dynamic == nullptr)
+ return;
+
+ for (__ElfN(Dyn) *dyn = dynamic; dyn->d_tag != DT_NULL; dyn++) {
+ switch (dyn->d_tag) {
+ case DT_SYMTAB:
+ dynsym = reinterpret_cast<__ElfN(Sym) *>(dyn->d_un.d_ptr);
+ break;
+ case DT_STRTAB:
+ dynstr = reinterpret_cast<char *>(dyn->d_un.d_ptr);
+ break;
+ case DT_JMPREL:
+ jmprel = reinterpret_cast<void *>(dyn->d_un.d_ptr);
+ break;
+ case DT_PLTRELSZ:
+ pltrel_size = dyn->d_un.d_val;
+ break;
+ case DT_PLTREL:
+ reltype = dyn->d_un.d_val;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ bool symbol_is_available(const char *sym) const
+ {
+ if (jmprel == nullptr)
+ return false;
+
+ switch (reltype) {
+ case DT_REL:
+ return do_symbol_is_available(reinterpret_cast<__ElfN(Rel) *>(jmprel), sym);
+ break;
+ case DT_RELA:
+ return do_symbol_is_available(reinterpret_cast<__ElfN(Rela) *>(jmprel), sym);
+ break;
+ default: // no relocations
+ break;
+ }
+ return false;
+ }
+
+private:
+ plt_sym_resolver();
+
+ template<typename Rel>
+ bool do_symbol_is_available(const Rel *rel_table, const char *sym) const
+ {
+ if (rel_table == nullptr || pltrel_size == 0)
+ return false;
+
+ size_t rel_cnt = pltrel_size / sizeof(Rel);
+ for (const Rel *rel = rel_table, *rel_end = rel_table + rel_cnt;
+ rel < rel_end; rel++) {
+ if (strcmp(sym, rel_to_symname(rel)) == 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ template<typename Rel>
+ inline char *rel_to_symname(const Rel *rel) const
+ {
+ return dynstr + dynsym[rel->getSymbol()].st_name;
+ }
+};
+
+BOOL module_is_sanitized(void *handle)
+{
+ plt_sym_resolver psr(handle);
+ psr.walk_dynamic_section();
+ return psr.symbol_is_available("__asan_init") ? TRUE : FALSE;
+}
diff --git a/src/pal/src/loader/tizenasanenvmodule.h b/src/pal/src/loader/tizenasanenvmodule.h
new file mode 100644
index 0000000..175c8d7
--- /dev/null
+++ b/src/pal/src/loader/tizenasanenvmodule.h
@@ -0,0 +1,8 @@
+#ifndef TIZENASANENVMODULE_H_
+#define TIZENASANENVMODULE_H_
+
+#include <pal_mstypes.h>
+
+BOOL module_is_sanitized(void *handle);
+
+#endif // TIZENASANENVMODULE_H_