diff --git a/glibc-testsuite.changes b/glibc-testsuite.changes index 2091e10..87b8f63 100644 --- a/glibc-testsuite.changes +++ b/glibc-testsuite.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Jul 27 09:08:21 UTC 2015 - schwab@suse.de + +- pthread-join-deadlock.patch: Use IE model for static variables in + libc.so, libpthread.so and rtld (bsc#930015, BZ #18457) + ------------------------------------------------------------------- Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de diff --git a/glibc-testsuite.spec b/glibc-testsuite.spec index 5c759bf..fc14097 100644 --- a/glibc-testsuite.spec +++ b/glibc-testsuite.spec @@ -251,6 +251,8 @@ Patch1008: nss-separate-state-getXXent.patch Patch1009: aarch64-sigstksz.patch # PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502) Patch1010: heap-top-corruption.patch +# PATCH-FIX-UPSTREAM Use IE model for static variables in libc.so, libpthread.so and rtld (BZ #18457) +Patch1011: pthread-join-deadlock.patch ### # Patches awaiting upstream approval @@ -265,8 +267,6 @@ Patch2003: abort-no-flush.patch Patch2005: glibc-memset-nontemporal.diff # PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197) Patch2006: ibm93x-redundant-shift-si.patch -# PATCH-FIX-UPSTREAM Don't require rtld lock to store static TLS offset in the DTV (BZ #18457) -Patch2007: pthread-join-deadlock.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -477,13 +477,13 @@ rm nscd/s-stamp %patch1008 -p1 %patch1009 -p1 %patch1010 -p1 +%patch1011 -p1 %patch2000 -p1 %patch2002 -p1 %patch2003 -p1 %patch2005 -p1 %patch2006 -p1 -%patch2007 -p1 %patch3000 diff --git a/glibc-utils.changes b/glibc-utils.changes index 2091e10..87b8f63 100644 --- a/glibc-utils.changes +++ b/glibc-utils.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Jul 27 09:08:21 UTC 2015 - schwab@suse.de + +- pthread-join-deadlock.patch: Use IE model for static variables in + libc.so, libpthread.so and rtld (bsc#930015, BZ #18457) + ------------------------------------------------------------------- Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de diff --git a/glibc-utils.spec b/glibc-utils.spec index 3405071..fcb2297 100644 --- a/glibc-utils.spec +++ b/glibc-utils.spec @@ -250,6 +250,8 @@ Patch1008: nss-separate-state-getXXent.patch Patch1009: aarch64-sigstksz.patch # PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502) Patch1010: heap-top-corruption.patch +# PATCH-FIX-UPSTREAM Use IE model for static variables in libc.so, libpthread.so and rtld (BZ #18457) +Patch1011: pthread-join-deadlock.patch ### # Patches awaiting upstream approval @@ -264,8 +266,6 @@ Patch2003: abort-no-flush.patch Patch2005: glibc-memset-nontemporal.diff # PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197) Patch2006: ibm93x-redundant-shift-si.patch -# PATCH-FIX-UPSTREAM Don't require rtld lock to store static TLS offset in the DTV (BZ #18457) -Patch2007: pthread-join-deadlock.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -477,13 +477,13 @@ rm nscd/s-stamp %patch1008 -p1 %patch1009 -p1 %patch1010 -p1 +%patch1011 -p1 %patch2000 -p1 %patch2002 -p1 %patch2003 -p1 %patch2005 -p1 %patch2006 -p1 -%patch2007 -p1 %patch3000 diff --git a/glibc.changes b/glibc.changes index 2091e10..87b8f63 100644 --- a/glibc.changes +++ b/glibc.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Mon Jul 27 09:08:21 UTC 2015 - schwab@suse.de + +- pthread-join-deadlock.patch: Use IE model for static variables in + libc.so, libpthread.so and rtld (bsc#930015, BZ #18457) + ------------------------------------------------------------------- Wed Jul 22 09:13:48 UTC 2015 - schwab@suse.de diff --git a/glibc.spec b/glibc.spec index a3c1874..8486816 100644 --- a/glibc.spec +++ b/glibc.spec @@ -251,6 +251,8 @@ Patch1008: nss-separate-state-getXXent.patch Patch1009: aarch64-sigstksz.patch # PATCH-FIX-UPSTREAM malloc: Do not corrupt the top of a threaded heap if top chunk is MINSIZE (BZ #18502) Patch1010: heap-top-corruption.patch +# PATCH-FIX-UPSTREAM Use IE model for static variables in libc.so, libpthread.so and rtld (BZ #18457) +Patch1011: pthread-join-deadlock.patch ### # Patches awaiting upstream approval @@ -265,8 +267,6 @@ Patch2003: abort-no-flush.patch Patch2005: glibc-memset-nontemporal.diff # PATCH-FIX-UPSTREAM Avoid redundant shift character in iconv output at block boundary (BZ #17197) Patch2006: ibm93x-redundant-shift-si.patch -# PATCH-FIX-UPSTREAM Don't require rtld lock to store static TLS offset in the DTV (BZ #18457) -Patch2007: pthread-join-deadlock.patch # Non-glibc patches # PATCH-FIX-OPENSUSE Remove debianisms from manpages @@ -477,13 +477,13 @@ rm nscd/s-stamp %patch1008 -p1 %patch1009 -p1 %patch1010 -p1 +%patch1011 -p1 %patch2000 -p1 %patch2002 -p1 %patch2003 -p1 %patch2005 -p1 %patch2006 -p1 -%patch2007 -p1 %patch3000 diff --git a/pthread-join-deadlock.patch b/pthread-join-deadlock.patch index 34c60d6..e3f6299 100644 --- a/pthread-join-deadlock.patch +++ b/pthread-join-deadlock.patch @@ -1,69 +1,37 @@ - [PR dynamic-link/18457] - * elf/dl-tls.c (tls_get_addr_tail): Don't take the rtld lock - if we already have a final static TLS offset. - * nptl/tst-join7.c, nptl/tst-join7mod.c: New. +2015-07-24 Siddhesh Poyarekar -Index: glibc-2.21/elf/dl-tls.c + [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/elf/dl-tls.c -+++ glibc-2.21/elf/dl-tls.c -@@ -755,30 +755,44 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t - the_map = listp->slotinfo[idx].map; - } +--- glibc-2.21.orig/Makeconfig ++++ glibc-2.21/Makeconfig +@@ -832,6 +832,10 @@ in-module = $(subst -,_,$(firstword $(li + $(libof-$(@F)) \ + libc)) -- /* Make sure that, if a dlopen running in parallel forces the -- variable into static storage, we'll wait until the address in the -- static TLS block is set up, and use that. If we're undecided -- yet, make sure we make the decision holding the lock as well. */ -- if (__glibc_unlikely (the_map->l_tls_offset -- != FORCED_DYNAMIC_TLS_OFFSET)) -+ /* If the TLS block for the map is already assigned to dynamic or to -+ static TLS, avoid the lock. Be careful to use the same value for -+ both tests; if we reloaded it, the second test might mistake -+ forced dynamic for an offset. Now, if the decision hasn't been -+ made, take the rtld lock, so that an ongoing dlopen gets a chance -+ to complete, and then retest; if the decision is still pending, -+ force the module to dynamic TLS. */ -+ ptrdiff_t offset = atomic_load_relaxed (&the_map->l_tls_offset); -+ if (__glibc_unlikely (offset != FORCED_DYNAMIC_TLS_OFFSET)) - { -+ if (__glibc_unlikely (offset != NO_TLS_OFFSET)) -+ goto static_tls; - __rtld_lock_lock_recursive (GL(dl_load_lock)); -- if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET)) -+ offset = the_map->l_tls_offset; -+ if (__glibc_likely (offset == NO_TLS_OFFSET)) - { - the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET; - __rtld_lock_unlock_recursive (GL(dl_load_lock)); - } -- else if (__glibc_likely (the_map->l_tls_offset -- != FORCED_DYNAMIC_TLS_OFFSET)) -+ else if (__glibc_likely (offset != FORCED_DYNAMIC_TLS_OFFSET)) - { -+ /* The decision is made, and it is final. We use the value -+ we've already loaded, but we could even load the offset -+ after releasing the lock, since it won't change. Should -+ the module be released while another thread references -+ one of its TLS variables, that's undefined behavior. */ -+ __rtld_lock_unlock_recursive (GL(dl_load_lock)); ++# 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,) + -+ static_tls: -+ ; -+ - #if TLS_TCB_AT_TP -- void *p = (char *) THREAD_SELF - the_map->l_tls_offset; -+ void *p = (char *) THREAD_SELF - offset; - #elif TLS_DTV_AT_TP -- void *p = (char *) THREAD_SELF + the_map->l_tls_offset + TLS_PRE_TCB_SIZE; -+ void *p = (char *) THREAD_SELF + offset + TLS_PRE_TCB_SIZE; - #else - # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" - #endif -- __rtld_lock_unlock_recursive (GL(dl_load_lock)); + module-cppflags-real = -include $(common-objpfx)libc-modules.h \ + -DMODULE_NAME=$(in-module) - dtv[GET_ADDR_MODULE].pointer.is_static = true; - dtv[GET_ADDR_MODULE].pointer.val = p; +@@ -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-$(. */ ++ +#include + ++/* 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; ++ if (f) ++ dlclose (f); ++ else ++ return 1; ++ + return 0; +} + @@ -120,9 +122,30 @@ Index: glibc-2.21/nptl/tst-join7mod.c =================================================================== --- /dev/null +++ glibc-2.21/nptl/tst-join7mod.c -@@ -0,0 +1,29 @@ +@@ -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 ++ . */ ++ +#include ++#include +#include ++#include + +static pthread_t th; +static int running = 1; @@ -130,23 +153,35 @@ Index: glibc-2.21/nptl/tst-join7mod.c +static void * +test_run (void *p) +{ -+ while (running) -+ fprintf (stderr, "XXX test_run\n"); -+ fprintf (stderr, "XXX test_run FINISHED\n"); ++ while (atomic_load_relaxed (&running)) ++ printf ("Test running\n"); ++ printf ("Test finished\n"); + return NULL; +} + +static void __attribute__ ((constructor)) +do_init (void) +{ -+ pthread_create (&th, NULL, test_run, NULL); ++ 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) +{ -+ running = 0; -+ fprintf (stderr, "thread_join...\n"); -+ pthread_join (th, NULL); -+ fprintf (stderr, "thread_join DONE\n"); ++ 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"); +}