OSDN Git Service

linker_asan: Translate absolute dlopen paths to use asan-libraries.
authorDimitry Ivanov <dimitry@google.com>
Wed, 10 Aug 2016 02:38:43 +0000 (19:38 -0700)
committerDimitry Ivanov <dimitry@google.com>
Thu, 11 Aug 2016 04:37:50 +0000 (21:37 -0700)
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
(cherry picked from commit 5aa67675f853af9588ac9274ecf86d7858695ce2)

linker/linker.cpp

index 9b90028..7d34823 100644 (file)
@@ -91,32 +91,35 @@ static soinfo* solist;
 static soinfo* sonext;
 static soinfo* somain; // main process, always the one after libdl_info
 
-static const char* const kDefaultLdPaths[] = {
 #if defined(__LP64__)
-  "/system/lib64",
-  "/vendor/lib64",
+static const char* const kSystemLibDir     = "/system/lib64";
+static const char* const kVendorLibDir     = "/vendor/lib64";
+static const char* const kAsanSystemLibDir = "/data/lib64";
+static const char* const kAsanVendorLibDir = "/data/vendor/lib64";
 #else
-  "/system/lib",
-  "/vendor/lib",
+static const char* const kSystemLibDir     = "/system/lib";
+static const char* const kVendorLibDir     = "/vendor/lib";
+static const char* const kAsanSystemLibDir = "/data/lib";
+static const char* const kAsanVendorLibDir = "/data/vendor/lib";
 #endif
+
+static const char* const kDefaultLdPaths[] = {
+  kSystemLibDir,
+  kVendorLibDir,
   nullptr
 };
 
 static const char* const kAsanDefaultLdPaths[] = {
-#if defined(__LP64__)
-  "/data/lib64",
-  "/system/lib64",
-  "/data/vendor/lib64",
-  "/vendor/lib64",
-#else
-  "/data/lib",
-  "/system/lib",
-  "/data/vendor/lib",
-  "/vendor/lib",
-#endif
+  kAsanSystemLibDir,
+  kSystemLibDir,
+  kAsanVendorLibDir,
+  kVendorLibDir,
   nullptr
 };
 
+// Is ASAN enabled?
+static bool g_is_asan = false;
+
 static bool is_system_library(const std::string& realpath) {
   for (const auto& dir : g_default_namespace.get_default_library_paths()) {
     if (file_is_in_dir(realpath, dir)) {
@@ -126,11 +129,16 @@ static bool is_system_library(const std::string& realpath) {
   return false;
 }
 
-#if defined(__LP64__)
-static const char* const kSystemLibDir = "/system/lib64";
-#else
-static const char* const kSystemLibDir = "/system/lib";
-#endif
+// Checks if the file exists and not a directory.
+static bool file_exists(const char* path) {
+  int fd = TEMP_FAILURE_RETRY(open(path, O_RDONLY | O_CLOEXEC));
+  if (fd == -1) {
+    return false;
+  } else {
+    close(fd);
+    return true;
+  }
+}
 
 // TODO(dimitry): The grey-list is a workaround for http://b/26394120 ---
 // gradually remove libraries from this list until it is gone.
@@ -1828,8 +1836,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;
-  soinfo* si = find_library(ns, name, flags, extinfo, caller);
+  soinfo* si = find_library(ns, translated_name, flags, extinfo, caller);
   if (si != nullptr) {
     failure_guard.disable();
     si->call_constructors();
@@ -3283,6 +3310,7 @@ static void init_default_namespace() {
   const char* bname = basename(interp);
   if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0)) {
     g_default_ld_paths = kAsanDefaultLdPaths;
+    g_is_asan = true;
   } else {
     g_default_ld_paths = kDefaultLdPaths;
   }