OSDN Git Service

Lock on dl_interate_phdr
authorDmitriy Ivanov <dimitry@google.com>
Mon, 29 Jun 2015 21:48:25 +0000 (14:48 -0700)
committerDmitriy Ivanov <dimitry@google.com>
Mon, 29 Jun 2015 22:14:28 +0000 (15:14 -0700)
There is possibility of someone dlclosing a library
while dl_iterate_phdr in progress which can lead to
dl_iterate_phdr calling callback with invalid address
if it was unmapped by dlclose.

Bug: http://b/22047255
Change-Id: I3fc0d9fd2c51fb36fd34cb035f37271fa893a7be
(cherry picked from commit f7d5bf334dc4bc5b7399d4c8268e1b0bf676548f)

linker/dlfcn.cpp
linker/linker.cpp
linker/linker.h

index a70abf5..ef454ab 100644 (file)
@@ -158,6 +158,11 @@ int dlclose(void* handle) {
   return 0;
 }
 
+int dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
+  ScopedPthreadMutexLocker locker(&g_dl_mutex);
+  return do_dl_iterate_phdr(cb, data);
+}
+
 void android_set_application_target_sdk_version(uint32_t target) {
   // lock to avoid modification in the middle of dlopen.
   ScopedPthreadMutexLocker locker(&g_dl_mutex);
index 5d54089..c6e569a 100644 (file)
@@ -393,7 +393,7 @@ _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) {
 
 // Here, we only have to provide a callback to iterate across all the
 // loaded libraries. gcc_eh does the rest.
-int dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
+int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) {
   int rv = 0;
   for (soinfo* si = solist; si != nullptr; si = si->next) {
     dl_phdr_info dl_info;
index 43b1e07..9bca7f3 100644 (file)
@@ -428,6 +428,8 @@ void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
 soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
 void do_dlclose(soinfo* si);
 
+int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
+
 const ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle);
 soinfo* find_containing_library(const void* addr);