This is the mail archive of the
libc-ports@sources.redhat.com
mailing list for the libc-ports project.
[RFC][PATCH] MIPS - SEGV at do_lookup_x()
- From: viju vincent <vijuvince at gmail dot com>
- To: libc-ports at sources dot redhat dot com
- Cc: viju vincent <vijuvince at gmail dot com>
- Date: Mon, 13 Feb 2012 20:15:10 +0530
- Subject: [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