linker_asan: Translate absolute dlopen paths to use asan-libraries.

This patch enables absolute path translation to instrumented library
when linker_asan is in use.

Test: adb shell cat /proc/<rlid pid>/maps | grep libril-qc-qmi-1.so
      check that it is mapped from /data/vendor/lib64 and not /vendor/lib64
Bug: http://b/30320104
Change-Id: I3bc24754b192afc0a72d6f3801f7b42141ce715b
This commit is contained in:
Dimitry Ivanov 2016-08-09 19:38:43 -07:00
parent 7e2d49ae3e
commit 5aa67675f8
1 changed files with 50 additions and 23 deletions

View File

@ -155,32 +155,35 @@ static soinfo* solist;
static soinfo* sonext; static soinfo* sonext;
static soinfo* somain; // main process, always the one after libdl_info static soinfo* somain; // main process, always the one after libdl_info
static const char* const kDefaultLdPaths[] = {
#if defined(__LP64__) #if defined(__LP64__)
"/system/lib64", static const char* const kSystemLibDir = "/system/lib64";
"/vendor/lib64", static const char* const kVendorLibDir = "/vendor/lib64";
static const char* const kAsanSystemLibDir = "/data/lib64";
static const char* const kAsanVendorLibDir = "/data/vendor/lib64";
#else #else
"/system/lib", static const char* const kSystemLibDir = "/system/lib";
"/vendor/lib", static const char* const kVendorLibDir = "/vendor/lib";
static const char* const kAsanSystemLibDir = "/data/lib";
static const char* const kAsanVendorLibDir = "/data/vendor/lib";
#endif #endif
static const char* const kDefaultLdPaths[] = {
kSystemLibDir,
kVendorLibDir,
nullptr nullptr
}; };
static const char* const kAsanDefaultLdPaths[] = { static const char* const kAsanDefaultLdPaths[] = {
#if defined(__LP64__) kAsanSystemLibDir,
"/data/lib64", kSystemLibDir,
"/system/lib64", kAsanVendorLibDir,
"/data/vendor/lib64", kVendorLibDir,
"/vendor/lib64",
#else
"/data/lib",
"/system/lib",
"/data/vendor/lib",
"/vendor/lib",
#endif
nullptr nullptr
}; };
// Is ASAN enabled?
static bool g_is_asan = false;
static bool is_system_library(const std::string& realpath) { static bool is_system_library(const std::string& realpath) {
for (const auto& dir : g_default_namespace.get_default_library_paths()) { for (const auto& dir : g_default_namespace.get_default_library_paths()) {
if (file_is_in_dir(realpath, dir)) { if (file_is_in_dir(realpath, dir)) {
@ -190,12 +193,16 @@ static bool is_system_library(const std::string& realpath) {
return false; return false;
} }
#if defined(__LP64__) // Checks if the file exists and not a directory.
static const char* const kSystemLibDir = "/system/lib64"; static bool file_exists(const char* path) {
#else int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
static const char* const kSystemLibDir = "/system/lib"; if (fd == -1) {
#endif return false;
} else {
close(fd);
return true;
}
}
static std::string dirname(const char *path); static std::string dirname(const char *path);
// TODO(dimitry): The grey-list is a workaround for http://b/26394120 --- // TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
@ -2370,8 +2377,27 @@ void* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo,
} }
} }
std::string asan_name_holder;
const char* translated_name = name;
if (g_is_asan) {
if (file_is_in_dir(name, kSystemLibDir)) {
asan_name_holder = std::string(kAsanSystemLibDir) + "/" + basename(name);
if (file_exists(asan_name_holder.c_str())) {
translated_name = asan_name_holder.c_str();
PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
}
} else if (file_is_in_dir(name, kVendorLibDir)) {
asan_name_holder = std::string(kAsanVendorLibDir) + "/" + basename(name);
if (file_exists(asan_name_holder.c_str())) {
translated_name = asan_name_holder.c_str();
PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
}
}
}
ProtectedDataGuard guard; ProtectedDataGuard guard;
soinfo* si = find_library(ns, name, flags, extinfo, caller); soinfo* si = find_library(ns, translated_name, flags, extinfo, caller);
if (si != nullptr) { if (si != nullptr) {
si->call_constructors(); si->call_constructors();
return si->to_handle(); return si->to_handle();
@ -4122,6 +4148,7 @@ static void init_default_namespace() {
const char* bname = basename(interp); const char* bname = basename(interp);
if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0)) { if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0)) {
g_default_ld_paths = kAsanDefaultLdPaths; g_default_ld_paths = kAsanDefaultLdPaths;
g_is_asan = true;
} else { } else {
g_default_ld_paths = kDefaultLdPaths; g_default_ld_paths = kDefaultLdPaths;
} }