Andreas Schwab
f26bd5d9b4
- pthread-join-deadlock.patch: Use IE model for static variables in libc.so, libpthread.so and rtld (bsc#930015, BZ #18457) OBS-URL: https://build.opensuse.org/request/show/318958 OBS-URL: https://build.opensuse.org/package/show/Base:System/glibc?expand=0&rev=409
188 lines
6.7 KiB
Diff
188 lines
6.7 KiB
Diff
2015-07-24 Siddhesh Poyarekar <siddhesh@redhat.com>
|
|
|
|
[BZ #18457]
|
|
* nptl/Makefile (tests): New test case tst-join7.
|
|
(modules-names): New test case module tst-join7mod.
|
|
* nptl/tst-join7.c: New file.
|
|
* nptl/tst-join7mod.c: New file.
|
|
* Makeconfig (tls-model): Pass -ftls-model=initial-exec for
|
|
all translation units in libc.so, libpthread.so and rtld.
|
|
|
|
Index: glibc-2.21/Makeconfig
|
|
===================================================================
|
|
--- glibc-2.21.orig/Makeconfig
|
|
+++ glibc-2.21/Makeconfig
|
|
@@ -832,6 +832,10 @@ in-module = $(subst -,_,$(firstword $(li
|
|
$(libof-$(@F)) \
|
|
libc))
|
|
|
|
+# Build ld.so, libc.so and libpthread.so with -ftls-model=initial-exec
|
|
+tls-model = $(if $(filter libpthread rtld \
|
|
+ libc,$(in-module)),-ftls-model=initial-exec,)
|
|
+
|
|
module-cppflags-real = -include $(common-objpfx)libc-modules.h \
|
|
-DMODULE_NAME=$(in-module)
|
|
|
|
@@ -855,7 +859,7 @@ CPPFLAGS = $(config-extra-cppflags) $(CP
|
|
override CFLAGS = -std=gnu99 $(gnu89-inline-CFLAGS) $(config-extra-cflags) \
|
|
$(filter-out %frame-pointer,$(+cflags)) $(+gccwarn-c) \
|
|
$(sysdep-CFLAGS) $(CFLAGS-$(suffix $@)) $(CFLAGS-$(<F)) \
|
|
- $(CFLAGS-$(@F)) \
|
|
+ $(CFLAGS-$(@F)) $(tls-model) \
|
|
$(foreach lib,$(libof-$(basename $(@F))) \
|
|
$(libof-$(<F)) $(libof-$(@F)),$(CFLAGS-$(lib)))
|
|
override CXXFLAGS = $(c++-sysincludes) \
|
|
Index: glibc-2.21/nptl/Makefile
|
|
===================================================================
|
|
--- glibc-2.21.orig/nptl/Makefile
|
|
+++ glibc-2.21/nptl/Makefile
|
|
@@ -234,7 +234,7 @@ tests = tst-typesizes \
|
|
tst-basic7 \
|
|
tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
|
|
tst-raise1 \
|
|
- tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 \
|
|
+ tst-join1 tst-join2 tst-join3 tst-join4 tst-join5 tst-join6 tst-join7 \
|
|
tst-detach1 \
|
|
tst-eintr1 tst-eintr2 tst-eintr3 tst-eintr4 tst-eintr5 \
|
|
tst-tsd1 tst-tsd2 tst-tsd3 tst-tsd4 tst-tsd5 tst-tsd6 \
|
|
@@ -312,7 +312,8 @@ endif
|
|
modules-names = tst-atfork2mod tst-tls3mod tst-tls4moda tst-tls4modb \
|
|
tst-tls5mod tst-tls5moda tst-tls5modb tst-tls5modc \
|
|
tst-tls5modd tst-tls5mode tst-tls5modf tst-stack4mod \
|
|
- tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod
|
|
+ tst-_res1mod1 tst-_res1mod2 tst-execstack-mod tst-fini1mod \
|
|
+ tst-join7mod
|
|
extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) tst-cleanup4aux.o
|
|
test-extras += $(modules-names) tst-cleanup4aux
|
|
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
|
|
@@ -517,6 +518,11 @@ $(objpfx)tst-tls6.out: tst-tls6.sh $(obj
|
|
$(evaluate-test)
|
|
endif
|
|
|
|
+$(objpfx)tst-join7: $(libdl) $(shared-thread-library)
|
|
+$(objpfx)tst-join7.out: $(objpfx)tst-join7mod.so
|
|
+$(objpfx)tst-join7mod.so: $(shared-thread-library)
|
|
+LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
|
|
+
|
|
$(objpfx)tst-dlsym1: $(libdl) $(shared-thread-library)
|
|
|
|
$(objpfx)tst-fini1: $(shared-thread-library) $(objpfx)tst-fini1mod.so
|
|
Index: glibc-2.21/nptl/tst-join7.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.21/nptl/tst-join7.c
|
|
@@ -0,0 +1,46 @@
|
|
+/* Verify that TLS access in separate thread in a dlopened library does not
|
|
+ deadlock.
|
|
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+
|
|
+#include <dlfcn.h>
|
|
+
|
|
+/* When one dynamically loads a module, which spawns a thread to perform some
|
|
+ activities, it could be possible that TLS storage is accessed for the first
|
|
+ time in that thread. This results in an allocation request within the
|
|
+ thread, which could result in an attempt to take the rtld load_lock. This
|
|
+ is a problem because it would then deadlock with the dlopen (which owns the
|
|
+ lock), if the main thread is waiting for the spawned thread to exit. We can
|
|
+ at least ensure that this problem does not occur due to accesses within
|
|
+ libc.so, by marking TLS variables within libc.so as IE. The problem of an
|
|
+ arbitrary variable being accessed and constructed within such a thread still
|
|
+ exists but this test case does not verify that. */
|
|
+
|
|
+int
|
|
+do_test (void)
|
|
+{
|
|
+ void *f = dlopen ("tst-join7mod.so", RTLD_NOW | RTLD_GLOBAL);
|
|
+ if (f)
|
|
+ dlclose (f);
|
|
+ else
|
|
+ return 1;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#define TEST_FUNCTION do_test ()
|
|
+#include "../test-skeleton.c"
|
|
Index: glibc-2.21/nptl/tst-join7mod.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ glibc-2.21/nptl/tst-join7mod.c
|
|
@@ -0,0 +1,62 @@
|
|
+/* Verify that TLS access in separate thread in a dlopened library does not
|
|
+ deadlock - the module.
|
|
+ Copyright (C) 2015 Free Software Foundation, Inc.
|
|
+ This file is part of the GNU C Library.
|
|
+
|
|
+ The GNU C Library is free software; you can redistribute it and/or
|
|
+ modify it under the terms of the GNU Lesser General Public
|
|
+ License as published by the Free Software Foundation; either
|
|
+ version 2.1 of the License, or (at your option) any later version.
|
|
+
|
|
+ The GNU C Library is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
+ Lesser General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU Lesser General Public
|
|
+ License along with the GNU C Library; if not, see
|
|
+ <http://www.gnu.org/licenses/>. */
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <string.h>
|
|
+#include <pthread.h>
|
|
+#include <atomic.h>
|
|
+
|
|
+static pthread_t th;
|
|
+static int running = 1;
|
|
+
|
|
+static void *
|
|
+test_run (void *p)
|
|
+{
|
|
+ while (atomic_load_relaxed (&running))
|
|
+ printf ("Test running\n");
|
|
+ printf ("Test finished\n");
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static void __attribute__ ((constructor))
|
|
+do_init (void)
|
|
+{
|
|
+ int ret = pthread_create (&th, NULL, test_run, NULL);
|
|
+
|
|
+ if (ret != 0)
|
|
+ {
|
|
+ printf ("failed to create thread: %s (%d)\n", strerror (ret), ret);
|
|
+ exit (1);
|
|
+ }
|
|
+}
|
|
+
|
|
+static void __attribute__ ((destructor))
|
|
+do_end (void)
|
|
+{
|
|
+ atomic_store_relaxed (&running, 0);
|
|
+ int ret = pthread_join (th, NULL);
|
|
+
|
|
+ if (ret != 0)
|
|
+ {
|
|
+ printf ("pthread_join: %s(%d)\n", strerror (ret), ret);
|
|
+ exit (1);
|
|
+ }
|
|
+
|
|
+ printf ("Thread joined\n");
|
|
+}
|