From 3879d0382be6504998409400490f35eebae1189f Mon Sep 17 00:00:00 2001 From: Andrey Drobyshev Date: Tue, 16 Jul 2019 15:23:18 +0300 Subject: [Tizen] Implement filtering of sanitized libraries. 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 --- src/pal/src/CMakeLists.txt | 1 + src/pal/src/asan/asan_integration.cpp | 140 ++++++++++++++++++++++++++++++++++ src/pal/src/include/pal/module.h | 6 ++ src/pal/src/loader/module.cpp | 8 ++ 4 files changed, 155 insertions(+) create mode 100644 src/pal/src/asan/asan_integration.cpp 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 + +#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(dyn->d_un.d_ptr); + break; + case DT_JMPREL: + jmprel = reinterpret_cast(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 + 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 + 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; -- cgit v1.2.3