This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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]

Re: [BZ#17090/17620/17621]: fix DTV race, assert, and DTV_SURPLUS Static TLS limit


On Mar  4, 2015, Alan Modra <amodra@gmail.com> wrote:

> On Wed, Mar 04, 2015 at 03:35:29PM +1030, Alan Modra wrote:
>> As does nptl/tst-stack4 on x86_64 if tst-stack4mod.so is built with
>> -mtls-dialect=gnu2.

> This on top of your patch gets me past the segfault in free().

> I now hit another segfault, tst-stack4mod.c:function somehow has
> var == NULL.

Thanks, here's an incremental patch that fixes the attempt to release
the pointer from an entry past the end of the dtv (that you fixed
above); that ensures we don't use, in a TLS Descriptor, the generation
count of an earlier map that used the same dtv slot (this ensures we
update the DTV instead of happily using a NULL pointer in there); and
that silences a -Wundef warning in nptl_db, that I had missed when I
updated the #ifs for the last-posted version of the patch.

I'm now running a full build and test cycle with the combined patch,
that I will post once it (hopefully ;-) completes successfully.


diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 311cc6d..20c7e33 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -674,13 +674,17 @@ _dl_update_slotinfo (unsigned long int req_modid)
 	      struct link_map *map = listp->slotinfo[cnt].map;
 	      if (map == NULL)
 		{
-		  /* If this modid was used at some point the memory
-		     might still be allocated.  */
-		  if (! dtv[total + cnt].pointer.is_static
-		      && dtv[total + cnt].pointer.val != TLS_DTV_UNALLOCATED)
-		    free (dtv[total + cnt].pointer.val);
-		  dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
-		  dtv[total + cnt].pointer.is_static = false;
+		  if (dtv[-1].counter >= total + cnt)
+		    {
+		      /* If this modid was used at some point the memory
+			 might still be allocated.  */
+		      if (! dtv[total + cnt].pointer.is_static
+			  && (dtv[total + cnt].pointer.val
+			      != TLS_DTV_UNALLOCATED))
+			free (dtv[total + cnt].pointer.val);
+		      dtv[total + cnt].pointer.val = TLS_DTV_UNALLOCATED;
+		      dtv[total + cnt].pointer.is_static = false;
+		    }
 
 		  continue;
 		}
diff --git a/elf/tlsdeschtab.h b/elf/tlsdeschtab.h
index d7e7955..d13b4e5 100644
--- a/elf/tlsdeschtab.h
+++ b/elf/tlsdeschtab.h
@@ -42,7 +42,7 @@ eq_tlsdesc (void *p, void *q)
   return tdp->tlsinfo.ti_offset == tdq->tlsinfo.ti_offset;
 }
 
-inline static int
+inline static size_t
 map_generation (struct link_map *map)
 {
   size_t idx = map->l_tls_modid;
@@ -58,7 +58,7 @@ map_generation (struct link_map *map)
 	     we can assume that, if the generation count is zero, we
 	     still haven't determined the generation count for this
 	     module.  */
-	  if (listp->slotinfo[idx].gen)
+	  if (listp->slotinfo[idx].map == map && listp->slotinfo[idx].gen)
 	    return listp->slotinfo[idx].gen;
 	  else
 	    break;
diff --git a/nptl_db/structs.def b/nptl_db/structs.def
index e7b3c6a..0d49a0a 100644
--- a/nptl_db/structs.def
+++ b/nptl_db/structs.def
@@ -35,7 +35,7 @@
 #  define DB_RTLD_GLOBAL_FIELD(field)		\
   DB_STRUCT_FIELD (rtld_global, _##field)	\
   DB_MAIN_VARIABLE (_##field)
-# elif SHARED
+# elif defined SHARED
 #  define DB_RTLD_GLOBAL_FIELD(field)		\
   DB_STRUCT_FIELD (rtld_global, _##field)
 # else


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer


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