rtld-elf - restore old tls/tcb code
authorAlex Hornung <ahornung@gmail.com>
Sun, 24 Jul 2011 13:45:50 +0000 (14:45 +0100)
committerAlex Hornung <ahornung@gmail.com>
Sun, 24 Jul 2011 13:52:20 +0000 (14:52 +0100)
 * This was ported incorrectly from FreBSD; the dtv in the TCB needs to
   be updated properly.

 * This fixes a fairly tricky issue that appears in threaded programs
   using dlopen() and family, such as php and Java. It presented itself
   as a strcmp segfault in object_match_name() due to a messed up STAILQ
   ->next pointer. The pointer was being messed up by the TLS code.

Reported-by: Peter Avalos, Antonio Huete, Francois Tigeot
libexec/rtld-elf/i386/reloc.c
libexec/rtld-elf/rtld.c
libexec/rtld-elf/x86_64/reloc.c

index 84e22b8..adf7774 100644 (file)
@@ -363,12 +363,9 @@ void *
 ___tls_get_addr(tls_index *ti)
 {
     struct tls_tcb *tcb;
-    Elf_Addr* dtv;
 
     tcb = tls_get_tcb();
-    dtv = (Elf_Addr*)tcb->tcb_dtv;
-
-    return tls_get_addr_common(&dtv, ti->ti_module, ti->ti_offset);
+    return tls_get_addr_common((Elf_Addr **)&tcb->tcb_dtv, ti->ti_module, ti->ti_offset);
 }
 
 /* Sun ABI */
@@ -376,20 +373,15 @@ void *
 __tls_get_addr(tls_index *ti)
 {
     struct tls_tcb *tcb;
-    Elf_Addr* dtv;
 
     tcb = tls_get_tcb();
-    dtv = (Elf_Addr*)tcb->tcb_dtv;
-
-    return tls_get_addr_common(&dtv, ti->ti_module, ti->ti_offset);
+    return tls_get_addr_common((Elf_Addr **)&tcb->tcb_dtv, ti->ti_module, ti->ti_offset);
 }
 
 /* Sun ABI */
 void *
 __tls_get_addr_tcb(struct tls_tcb *tcb, tls_index *ti)
 {
-    Elf_Addr* dtv = (Elf_Addr*)tcb->tcb_dtv;
-
-    return tls_get_addr_common(&dtv, ti->ti_module, ti->ti_offset);
+    return tls_get_addr_common((Elf_Addr **)&tcb->tcb_dtv, ti->ti_module, ti->ti_offset);
 }
 
index 65aeee0..c982a7c 100644 (file)
@@ -3362,7 +3362,6 @@ free_tls(struct tls_tcb *tcb)
     }
 
     free((void*) tls_start);
-    free((void*) dtv);
 }
 
 #else
index 8a0a31b..ca11a80 100644 (file)
@@ -381,18 +381,13 @@ reloc_jmpslots(Obj_Entry *obj)
 void *__tls_get_addr(tls_index *ti)
 {
     struct tls_tcb *tcb;
-    Elf_Addr* dtv;
 
     tcb = tls_get_tcb();
-    dtv = (Elf_Addr*)tcb->tcb_dtv;
-
-    return tls_get_addr_common(&dtv, ti->ti_module, ti->ti_offset);
+    return tls_get_addr_common((Elf_Addr **)&tcb->tcb_dtv, ti->ti_module, ti->ti_offset);
 }
 
 void *
 __tls_get_addr_tcb(struct tls_tcb *tcb, tls_index *ti)
 {
-    Elf_Addr* dtv = (Elf_Addr*)tcb->tcb_dtv;
-
-    return tls_get_addr_common(&dtv, ti->ti_module, ti->ti_offset);
+    return tls_get_addr_common((Elf_Addr **)&tcb->tcb_dtv, ti->ti_module, ti->ti_offset);
 }