summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Drobyshev <a.drobyshev@samsung.com>2019-07-16 15:23:18 +0300
committerAndrey Drobyshev <a.drobyshev@samsung.com>2019-07-19 17:15:54 +0300
commit3879d0382be6504998409400490f35eebae1189f (patch)
tree5eace4e2454b967eda1109c688203971335984bd
parent59075187072252b2f048d2b4616f3f86960a2be6 (diff)
downloadcoreclr-sandbox/adrob/asan.tar.gz
coreclr-sandbox/adrob/asan.tar.bz2
coreclr-sandbox/adrob/asan.zip
[Tizen] Implement filtering of sanitized libraries.sandbox/adrob/asan
pal/asan/asan_integration.cpp: parse ".dynamic" section (ELF dynamic array tags) of the module being added, find ".rel(a).plt" section and search it for presence of symbols with "__asan" prefix. Signed-off-by: Andrey Drobyshev <a.drobyshev@samsung.com>
-rw-r--r--src/pal/src/CMakeLists.txt1
-rw-r--r--src/pal/src/asan/asan_integration.cpp140
-rw-r--r--src/pal/src/include/pal/module.h6
-rw-r--r--src/pal/src/loader/module.cpp8
4 files changed, 155 insertions, 0 deletions
diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt
index 8e69ee9ee9..919f57e47b 100644
--- a/src/pal/src/CMakeLists.txt
+++ b/src/pal/src/CMakeLists.txt
@@ -178,6 +178,7 @@ if(PAL_CMAKE_PLATFORM_ARCH_ARM)
endif(PAL_CMAKE_PLATFORM_ARCH_ARM)
set(SOURCES
+ asan/asan_integration.cpp
cruntime/file.cpp
cruntime/filecrt.cpp
cruntime/malloc.cpp
diff --git a/src/pal/src/asan/asan_integration.cpp b/src/pal/src/asan/asan_integration.cpp
new file mode 100644
index 0000000000..122f9bcf96
--- /dev/null
+++ b/src/pal/src/asan/asan_integration.cpp
@@ -0,0 +1,140 @@
+#include "pal.h"
+#include "llvm/ELF.h"
+#include "pal/module.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);
+size_t strnlen(const char *s, size_t maxlen);
+}
+
+struct plt_sym_resolver {
+ static const char * const asan_prefix;
+
+ 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 is_sanitized() const
+ {
+ if (jmprel == nullptr)
+ return false;
+
+ switch (reltype) {
+ case DT_REL:
+ return find_asan_symbol(reinterpret_cast<__ElfN(Rel) *>(jmprel));
+ break;
+ case DT_RELA:
+ return find_asan_symbol(reinterpret_cast<__ElfN(Rela) *>(jmprel));
+ break;
+ default: // no relocations
+ break;
+ }
+ return false;
+ }
+
+private:
+ plt_sym_resolver();
+
+ template<typename Rel>
+ bool find_asan_symbol(const Rel *rel_table) const
+ {
+ if (rel_table == nullptr || pltrel_size == 0)
+ return false;
+
+ size_t rel_cnt = pltrel_size / sizeof(Rel);
+ size_t len = strnlen(asan_prefix, 6);
+ for (const Rel *rel = rel_table, *rel_end = rel_table + rel_cnt;
+ rel < rel_end; rel++) {
+ if (strncmp(asan_prefix, rel_to_symname(rel), len) == 0)
+ return true;
+ }
+
+ return false;
+ }
+
+ template<typename Rel>
+ inline char *rel_to_symname(const Rel *rel) const
+ {
+ return dynstr + dynsym[rel->getSymbol()].st_name;
+ }
+};
+const char * const plt_sym_resolver::asan_prefix = "__asan";
+
+PALAPI BOOL module_is_sanitized(MODSTRUCT *module)
+{
+ plt_sym_resolver psr(module->dl_handle);
+ psr.walk_dynamic_section();
+ return psr.is_sanitized();
+}
diff --git a/src/pal/src/include/pal/module.h b/src/pal/src/include/pal/module.h
index aacc326c64..2612ba141c 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 HAS_ADDRESS_SANITIZER
+ BOOL is_sanitized;
+#endif
+
#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN
ino_t inode;
dev_t device;
@@ -195,6 +199,8 @@ Return value :
--*/
MODSTRUCT *LOADGetPalLibrary();
+PALAPI BOOL module_is_sanitized(MODSTRUCT *module);
+
#ifdef __cplusplus
}
#endif // __cplusplus
diff --git a/src/pal/src/loader/module.cpp b/src/pal/src/loader/module.cpp
index e39cd6e41f..92fd4c6578 100644
--- a/src/pal/src/loader/module.cpp
+++ b/src/pal/src/loader/module.cpp
@@ -1555,6 +1555,10 @@ static MODSTRUCT *LOADAllocModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR name)
module->next = nullptr;
module->prev = nullptr;
+#ifdef HAS_ADDRESS_SANITIZER
+ module->is_sanitized = FALSE;
+#endif
+
module->lib_name = wide_name;
return module;
@@ -1622,6 +1626,10 @@ static MODSTRUCT *LOADAddModule(NATIVE_LIBRARY_HANDLE dl_handle, LPCSTR libraryN
exe_module.prev->next = module;
exe_module.prev = module;
+#ifdef HAS_ADDRESS_SANITIZER
+ module->is_sanitized = module_is_sanitized(module);
+#endif
+
#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN
module->inode = stat_buf.st_ino;
module->device = stat_buf.st_dev;