This is the mail archive of the libc-ports@sources.redhat.com mailing list for the libc-ports project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC][PATCH] MIPS - SEGV at do_lookup_x()


I noticed SEGV at do_lookup_x(), in case of lazy binding vs dlopen() on MIPS.
The test senario is,
  * Thread A is handling symbol resolution and context switch is happens.
  * Thread B starts running and calls dlopen().
    * Because of dlopen(), rtld internal management data is
reallocated or extended, and its address got changed.
  * Thread A wakes up and continues handling symbol resolution and
SEGV happens due to accessing of incorrect memory address.

Tested the same on ARM target and no issue found.
As per the comment present in glibc-ports-2.7/sysdeps/mips/dl-trampoline.c
In case of ARM and other architectures, _dl_fixup() is called and it
has thread locking mechanism.
and for mips __dl_runtime_resolve() is used.
{{{
/* Define mips specific runtime resolver. The function __dl_runtime_resolve
   is called from assembler function _dl_runtime_resolve which converts
   special argument registers t7 ($15) and t8 ($24):
     t7  address to return to the caller of the function
     t8  index for this function symbol in .dynsym
   to usual c arguments.

   Other architectures call fixup from dl-runtime.c in
   _dl_runtime_resolve.  MIPS instead calls __dl_runtime_resolve.  We
   have to use our own version because of the way the got section is
   treated on MIPS (we've also got ELF_MACHINE_PLT defined).  */
}}}

>From the glibc source investigation, it is observed that there is lock
present for ARM and other targets.
and it is (lock mechanism for _dl_fixup()) is committed as,
   * http://repo.or.cz/w/glibc.git/commit/df94b6412e0628cd577da0ce5626358a3967ee44?f=elf/dl-runtime.c

For mips, the __dl_runtime_resolve() doesn't have any locking
mechanism, this cause SEGV at do_lookup_x().
Added lock and unlock in __dl_runtime_resolve() by referring the lock
applied to _dl_fixup() in elf/dl-runtime.c
Attached the patch which fix the SEGV at do_lookup_x().
This issue is present in glibc 2.7 and 2.14.

Best regards,
Viju Vincent M
Sony India Software Centre.
Patch to resolve race between dlopen() and lazy binding on mips

Index: glibc-2.14/glibc-ports-2.14/sysdeps/mips/dl-trampoline.c
===================================================================
--- glibc-2.14.orig/glibc-ports-2.14/sysdeps/mips/dl-trampoline.c
+++ glibc-2.14/glibc-ports-2.14/sysdeps/mips/dl-trampoline.c
@@ -26,6 +26,7 @@
 #include <elf.h>
 #include <ldsodefs.h>
 #include <dl-machine.h>
+#include <sysdep-cancel.h>
 
 /* Get link map for callers object containing STUB_PC.  */
 static inline struct link_map *
@@ -153,17 +154,44 @@ __dl_runtime_resolve (ElfW(Word) sym_ind
 
 	    if (version->hash != 0)
 	      {
+                /* We need to keep the scope around so do some locking.  This is
+		   not necessary for objects which cannot be unloaded or when
+		   we are not using any threads (yet).  */
+		if (!RTLD_SINGLE_THREAD_P)
+		  THREAD_GSCOPE_SET_FLAG ();
+
 		sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l,
 					       &sym, l->l_scope, version,
 					       ELF_RTYPE_CLASS_PLT, 0, 0);
+
+                /* We are done with the global scope.  */
+		if (!RTLD_SINGLE_THREAD_P)
+		  THREAD_GSCOPE_RESET_FLAG ();
+
 		break;
 	      }
 	    /* Fall through.  */
 	  }
 	case 0:
+	  {
+          /* We need to keep the scope around so do some locking.  This is
+	     not necessary for objects which cannot be unloaded or when
+	     we are not using any threads (yet).  */
+	  int flags = DL_LOOKUP_ADD_DEPENDENCY;
+	  if (!RTLD_SINGLE_THREAD_P)
+	    {
+	      THREAD_GSCOPE_SET_FLAG ();
+	      flags |= DL_LOOKUP_GSCOPE_LOCK;
+	    }
+
 	  sym_map = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym,
 					 l->l_scope, 0, ELF_RTYPE_CLASS_PLT,
-					 DL_LOOKUP_ADD_DEPENDENCY, 0);
+					 flags, 0);
+
+          /* We are done with the global scope.  */
+	  if (!RTLD_SINGLE_THREAD_P)
+	    THREAD_GSCOPE_RESET_FLAG ();
+	  }
 	}
 
       /* Currently value contains the base load address of the object

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]