From e191c349605f44747b01f00331ca34eca923b953 Mon Sep 17 00:00:00 2001 From: Andrey Drobyshev Date: Tue, 16 Jul 2019 15:23:18 +0300 Subject: [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 --- src/pal/inc/pal.h | 8 ++ src/pal/src/CMakeLists.txt | 6 ++ src/pal/src/loader/module.cpp | 23 +++++ src/pal/src/loader/tizenasanenvmodule.cpp | 137 ++++++++++++++++++++++++++++++ src/pal/src/loader/tizenasanenvmodule.h | 8 ++ 5 files changed, 182 insertions(+) create mode 100644 src/pal/src/loader/tizenasanenvmodule.cpp create mode 100644 src/pal/src/loader/tizenasanenvmodule.h diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 08a35c8f62..abb25e889f 100644 --- a/src/pal/inc/pal.h +++ b/src/pal/inc/pal.h @@ -2678,6 +2678,14 @@ PAL_GetProcAddressDirect( IN NATIVE_LIBRARY_HANDLE dl_handle, IN LPCSTR lpProcName); +#ifdef TIZEN_ASAN_ENVIRONMENT +PALIMPORT +BOOL +PALAPI +PAL_IsSanitizedLibraryDirect( + IN NATIVE_LIBRARY_HANDLE dl_handle); +#endif + /*++ Function: PAL_LOADLoadPEFile diff --git a/src/pal/src/CMakeLists.txt b/src/pal/src/CMakeLists.txt index 3e2cee898c..3bc1dc89a0 100644 --- a/src/pal/src/CMakeLists.txt +++ b/src/pal/src/CMakeLists.txt @@ -286,6 +286,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 $) endif(NOT CLR_CMAKE_USE_SYSTEM_LIBUNWIND) diff --git a/src/pal/src/loader/module.cpp b/src/pal/src/loader/module.cpp index c817ffe2db..74156fd215 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 #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 @@ -688,6 +692,25 @@ PAL_GetProcAddressDirect( return address; } +#ifdef TIZEN_ASAN_ENVIRONMENT +/* +Function: + PAL_IsSanitizedLibraryDirect + + Check whether the native library is sanitized. + + Returns TRUE if the native library is sanitized; FALSE otherwise. +*/ +PALIMPORT +BOOL +PALAPI +PAL_IsSanitizedLibraryDirect( + IN NATIVE_LIBRARY_HANDLE dl_handle) +{ + return is_module_sanitized(dl_handle); +} +#endif // TIZEN_ASAN_ENVIRONMENT + /*++ Function: PAL_RegisterModule diff --git a/src/pal/src/loader/tizenasanenvmodule.cpp b/src/pal/src/loader/tizenasanenvmodule.cpp new file mode 100644 index 0000000000..4f9ed19863 --- /dev/null +++ b/src/pal/src/loader/tizenasanenvmodule.cpp @@ -0,0 +1,137 @@ +#include +#include "pal.h" +#include "llvm/ELF.h" +#include "tizenasanenvmodule.h" + +#if __LP64__ +using Addr = Elf64_Addr; +using Dyn = Elf64_Dyn; +using Sym = Elf64_Sym; +using Rel = Elf64_Rel; +using Rela = Elf64_Rela; +#else +using Addr = Elf32_Addr; +using Dyn = Elf32_Dyn; +using Sym = Elf32_Sym; +using Rel = Elf32_Rel; +using Rela = Elf32_Rela; +#endif + +/* + * Request arguments for dlinfo(). + */ +#define RTLD_DI_LINKMAP 2 /* Obtain link map. */ + +struct link_map { + Addr l_addr; /* Base Address of library */ + const char *l_name; /* Absolute Path to Library */ + 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 { + 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() + : dynsym(nullptr), dynstr(nullptr), reltype(-1), pltrel_size(0), + jmprel(nullptr) + {} + + bool init(void *handle) + { + struct link_map *lmap; + + if (handle == nullptr || dlinfo(handle, RTLD_DI_LINKMAP, &lmap) < 0) + return false; + + if (lmap == nullptr || lmap->l_ld == nullptr) + return false; + + return init_relocation_info(lmap->l_ld); + } + + bool is_symbol_available(const char *sym) const + { + switch (reltype) { + case DT_REL: + return is_symbol_available_in_rtable(reinterpret_cast(jmprel), sym); + case DT_RELA: + return is_symbol_available_in_rtable(reinterpret_cast(jmprel), sym); + default: // no relocations + break; + } + return false; + } + +private: + bool init_relocation_info(Dyn *dynamic) + { + for (Dyn *dyn = dynamic; dyn->d_tag != DT_NULL; ++dyn) { + switch (dyn->d_tag) { + case DT_SYMTAB: + dynsym = reinterpret_cast(dyn->d_un.d_ptr); + break; + case DT_STRTAB: + dynstr = reinterpret_cast(dyn->d_un.d_ptr); + break; + case DT_PLTREL: + reltype = dyn->d_un.d_val; + break; + case DT_PLTRELSZ: + pltrel_size = dyn->d_un.d_val; + break; + case DT_JMPREL: + jmprel = reinterpret_cast(dyn->d_un.d_ptr); + break; + default: + break; + } + } + + if (dynsym == nullptr || + dynstr == nullptr || + jmprel == nullptr || + pltrel_size == 0 || + (reltype != DT_REL && reltype != DT_RELA)) + return false; + + return true; + } + + template + bool is_symbol_available_in_rtable(const Rel *rel_table, const char *sym) const + { + if (rel_table == nullptr || pltrel_size == 0) + return false; + + const size_t rel_cnt = pltrel_size / sizeof(Rel); + const Rel *rel_end = rel_table + rel_cnt; + for (const Rel *rel = rel_table; rel < rel_end; ++rel) { + if (strcmp(sym, rel_to_symname(rel)) == 0) + return true; + } + + return false; + } + + template + inline char *rel_to_symname(const Rel *rel) const + { + return dynstr + dynsym[rel->getSymbol()].st_name; + } +}; + +BOOL is_module_sanitized(void *handle) +{ + plt_sym_resolver psr; + if (!psr.init(handle)) + return FALSE; + return psr.is_symbol_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 0000000000..094fa5ad46 --- /dev/null +++ b/src/pal/src/loader/tizenasanenvmodule.h @@ -0,0 +1,8 @@ +#ifndef TIZENASANENVMODULE_H_ +#define TIZENASANENVMODULE_H_ + +#include + +BOOL is_module_sanitized(void *handle); + +#endif // TIZENASANENVMODULE_H_ -- cgit v1.2.3