Blame SOURCES/glibc-rh1248208.patch

147e83
commit e400f3ccd36fe91d432cc7d45b4ccc799dece763
147e83
Author: Siddhesh Poyarekar <siddhesh@redhat.com>
147e83
Date:   Fri Jul 24 19:13:38 2015 +0530
147e83
147e83
    Use IE model for static variables in libc.so, libpthread.so and rtld
147e83
    
147e83
    The recently introduced TLS variables in the thread-local destructor
147e83
    implementation (__cxa_thread_atexit_impl) used the default GD access
147e83
    model, resulting in a call to __tls_get_addr.  This causes a deadlock
147e83
    with recent changes to the way TLS is initialized because DTV
147e83
    allocations are delayed and hence despite knowing the offset to the
147e83
    variable inside its TLS block, the thread has to take the global rtld
147e83
    lock to safely update the TLS offset.
147e83
    
147e83
    This causes deadlocks when a thread is instantiated and joined inside
147e83
    a destructor of a dlopen'd DSO.  The correct long term fix is to
147e83
    somehow not take the lock, but that will need a lot deeper change set
147e83
    to alter the way in which the big rtld lock is used.
147e83
    
147e83
    Instead, this patch just eliminates the call to __tls_get_addr for the
147e83
    thread-local variables inside libc.so, libpthread.so and rtld by
147e83
    building all of their units with -mtls-model=initial-exec.
147e83
    
147e83
    There were concerns that the static storage for TLS is limited and
147e83
    hence we should not be using it.  Additionally, dynamically loaded
147e83
    modules may result in libc.so looking for this static storage pretty
147e83
    late in static binaries.  Both concerns are valid when using TLSDESC
147e83
    since that is where one may attempt to allocate a TLS block from
147e83
    static storage for even those variables that are not IE.  They're not
147e83
    very strong arguments for the traditional TLS model though, since it
147e83
    assumes that the static storage would be used sparingly and definitely
147e83
    not by default.  Hence, for now this would only theoretically affect
147e83
    ARM architectures.
147e83
    
147e83
    The impact is hence limited to statically linked binaries that dlopen
147e83
    modules that in turn load libc.so, all that on arm hardware.  It seems
147e83
    like a small enough impact to justify fixing the larger problem that
147e83
    currently affects everything everywhere.
147e83
    
147e83
    This still does not solve the original problem completely.  That is,
147e83
    it is still possible to deadlock on the big rtld lock with a small
147e83
    tweak to the test case attached to this patch.  That problem is
147e83
    however not a regression in 2.22 and hence could be tackled as a
147e83
    separate project.  The test case is picked up as is from Alex's patch.
147e83
    
147e83
    This change has been tested to verify that it does not cause any
147e83
    issues on x86_64.
147e83
    
147e83
    ChangeLog:
147e83
    
147e83
    	[BZ #18457]
147e83
    	* nptl/Makefile (tests): New test case tst-join7.
147e83
    	(modules-names): New test case module tst-join7mod.
147e83
    	* nptl/tst-join7.c: New file.
147e83
    	* nptl/tst-join7mod.c: New file.
147e83
    	* Makeconfig (tls-model): Pass -ftls-model=initial-exec for
147e83
    	all translation units in libc.so, libpthread.so and rtld.
147e83
147e83
diff --git a/nptl/Makefile b/nptl/Makefile
147e83
index 140f063..aaca0a4 100644
147e83
--- a/nptl/Makefile
147e83
+++ b/nptl/Makefile
147e83
@@ -245,7 +245,7 @@ tests = tst-typesizes \
147e83
 	tst-basic7 \
147e83
 	tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
147e83
 	tst-raise1 \
147e83
-	tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
147e83
+	tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
147e83
 	tst-detach1 \
147e83
 	tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
147e83
 	tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 tst-tsd6 \
147e83
@@ -327,7 +327,8 @@ endif
147e83
 modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
147e83
 		tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
147e83
 		tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
147e83
-		tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
147e83
+		tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
147e83
+		tst-join7mod
147e83
 extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
147e83
 test-extras += $(modules-names) tst-cleanup4aux
147e83
 test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
147e83
@@ -532,6 +533,11 @@ $(objpfx)tst-tls6.out: tst-tls6.sh $(objpfx)tst-tls5 \
147e83
 		    $(rtld-installed-name) '$(test-wrapper-env)'
147e83
 endif
147e83
 
147e83
+$(objpfx)tst-join7: $(libdl) $(shared-thread-library)
147e83
+$(objpfx)tst-join7.out: $(objpfx)tst-join7mod.so
147e83
+$(objpfx)tst-join7mod.so: $(shared-thread-library)
147e83
+LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
147e83
+
147e83
 $(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library)
147e83
 
147e83
 $(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so
147e83
diff --git a/nptl/tst-join7.c b/nptl/tst-join7.c
147e83
new file mode 100644
147e83
index 0000000..439d0fc
147e83
--- /dev/null
147e83
+++ b/nptl/tst-join7.c
147e83
@@ -0,0 +1,46 @@
147e83
+/* Verify that TLS access in separate thread in a dlopened library does not
147e83
+   deadlock.
147e83
+   Copyright (C) 2015 Free Software Foundation, Inc.
147e83
+   This file is part of the GNU C Library.
147e83
+
147e83
+   The GNU C Library is free software; you can redistribute it and/or
147e83
+   modify it under the terms of the GNU Lesser General Public
147e83
+   License as published by the Free Software Foundation; either
147e83
+   version 2.1 of the License, or (at your option) any later version.
147e83
+
147e83
+   The GNU C Library is distributed in the hope that it will be useful,
147e83
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
147e83
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147e83
+   Lesser General Public License for more details.
147e83
+
147e83
+   You should have received a copy of the GNU Lesser General Public
147e83
+   License along with the GNU C Library; if not, see
147e83
+   <http://www.gnu.org/licenses/>.  */
147e83
+
147e83
+#include <dlfcn.h>
147e83
+
147e83
+/* When one dynamically loads a module, which spawns a thread to perform some
147e83
+   activities, it could be possible that TLS storage is accessed for the first
147e83
+   time in that thread.  This results in an allocation request within the
147e83
+   thread, which could result in an attempt to take the rtld load_lock.  This
147e83
+   is a problem because it would then deadlock with the dlopen (which owns the
147e83
+   lock), if the main thread is waiting for the spawned thread to exit.  We can
147e83
+   at least ensure that this problem does not occur due to accesses within
147e83
+   libc.so, by marking TLS variables within libc.so as IE.  The problem of an
147e83
+   arbitrary variable being accessed and constructed within such a thread still
147e83
+   exists but this test case does not verify that.  */
147e83
+
147e83
+int
147e83
+do_test (void)
147e83
+{
147e83
+  void *f = dlopen ("tst-join7mod.so", RTLD_NOW | RTLD_GLOBAL);
147e83
+  if (f)
147e83
+    dlclose (f);
147e83
+  else
147e83
+    return 1;
147e83
+
147e83
+  return 0;
147e83
+}
147e83
+
147e83
+#define TEST_FUNCTION do_test ()
147e83
+#include "../test-skeleton.c"
147e83
diff --git a/nptl/tst-join7mod.c b/nptl/tst-join7mod.c
147e83
new file mode 100644
147e83
index 0000000..92bb381
147e83
--- /dev/null
147e83
+++ b/nptl/tst-join7mod.c
147e83
@@ -0,0 +1,61 @@
147e83
+/* Verify that TLS access in separate thread in a dlopened library does not
147e83
+   deadlock - the module.
147e83
+   Copyright (C) 2015 Free Software Foundation, Inc.
147e83
+   This file is part of the GNU C Library.
147e83
+
147e83
+   The GNU C Library is free software; you can redistribute it and/or
147e83
+   modify it under the terms of the GNU Lesser General Public
147e83
+   License as published by the Free Software Foundation; either
147e83
+   version 2.1 of the License, or (at your option) any later version.
147e83
+
147e83
+   The GNU C Library is distributed in the hope that it will be useful,
147e83
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
147e83
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
147e83
+   Lesser General Public License for more details.
147e83
+
147e83
+   You should have received a copy of the GNU Lesser General Public
147e83
+   License along with the GNU C Library; if not, see
147e83
+   <http://www.gnu.org/licenses/>.  */
147e83
+
147e83
+#include <stdio.h>
147e83
+#include <pthread.h>
147e83
+#include <atomic.h>
147e83
+
147e83
+static pthread_t th;
147e83
+static int running = 1;
147e83
+
147e83
+static void *
147e83
+test_run (void *p)
147e83
+{
147e83
+  while (atomic_load_relaxed (&running))
147e83
+    printf ("Test running\n");
147e83
+  printf ("Test finished\n");
147e83
+  return NULL;
147e83
+}
147e83
+
147e83
+static void __attribute__ ((constructor))
147e83
+do_init (void)
147e83
+{
147e83
+  int ret = pthread_create (&th, NULL, test_run, NULL);
147e83
+
147e83
+  if (ret != 0)
147e83
+    {
147e83
+      printf ("failed to create thread: %s (%d)\n", strerror (ret), ret);
147e83
+      exit (1);
147e83
+    }
147e83
+}
147e83
+
147e83
+static void __attribute__ ((destructor))
147e83
+do_end (void)
147e83
+{
147e83
+  atomic_store_relaxed (&running, 0);
147e83
+  int ret = pthread_join (th, NULL);
147e83
+
147e83
+  if (ret != 0)
147e83
+    {
147e83
+      printf ("pthread_join: %s(%d)\n", strerror (ret), ret);
147e83
+      exit (1);
147e83
+    }
147e83
+
147e83
+  printf ("Thread joined\n");
147e83
+}
147e83
diff -pruN a/string/strerror_l.c b/string/strerror_l.c
147e83
--- a/string/strerror_l.c
147e83
+++ b/string/strerror_l.c
147e83
@@ -23,7 +23,7 @@
147e83
 #include <sys/param.h>
147e83
 
147e83
 
147e83
-static __thread char *last_value;
147e83
+static __thread char *last_value attribute_tls_model_ie;
147e83
 
147e83
 
147e83
 static const char *