summary refs log tree commit diff
path: root/elf/dl-tls.c
diff options
context:
space:
mode:
authorCarlos O'Donell <carlos@redhat.com>2014-02-25 13:00:36 -0500
committerCarlos O'Donell <carlos@redhat.com>2014-02-25 13:18:15 -0500
commitd050367659e04685a0eab910e86ea6829a8d24f9 (patch)
treeeb094a22fb28449c7723b9463c388505ca31a5a3 /elf/dl-tls.c
parent4cbf380ce948ca15a965a78f0c1a092cf5956792 (diff)
downloadglibc-d050367659e04685a0eab910e86ea6829a8d24f9.tar.gz
glibc-d050367659e04685a0eab910e86ea6829a8d24f9.tar.xz
glibc-d050367659e04685a0eab910e86ea6829a8d24f9.zip
BZ #16613: Support TLS in audit libraries.
This commit fixes a bug where the dynamic loader would crash
when loading audit libraries, via LD_AUDIT, where those libraries
used TLS. The dynamic loader was not considering that the audit
libraries would use TLS and failed to bump the TLS generation
counter leaving TLS usage inconsistent after loading the audit
libraries.

https://sourceware.org/ml/libc-alpha/2014-02/msg00569.html
Diffstat (limited to 'elf/dl-tls.c')
-rw-r--r--elf/dl-tls.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 9454d06d72..5204fdaac0 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -105,6 +105,33 @@ _dl_next_tls_modid (void)
 }
 
 
+size_t
+internal_function
+_dl_count_modids (void)
+{
+  /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
+     we fail to load a module and unload it leaving a gap.  If we don't
+     have gaps then the number of modids is the current maximum so
+     return that.  */
+  if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
+    return GL(dl_tls_max_dtv_idx);
+
+  /* We have gaps and are forced to count the non-NULL entries.  */
+  size_t n = 0;
+  struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list);
+  while (runp != NULL)
+    {
+      for (size_t i = 0; i < runp->len; ++i)
+	if (runp->slotinfo[i].map != NULL)
+	  ++n;
+
+      runp = runp->next;
+    }
+
+  return n;
+}
+
+
 #ifdef SHARED
 void
 internal_function
@@ -407,6 +434,7 @@ _dl_allocate_tls_init (void *result)
 
 	  /* Keep track of the maximum generation number.  This might
 	     not be the generation counter.  */
+	  assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation));
 	  maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
 
 	  if (map->l_tls_offset == NO_TLS_OFFSET