Created attachment 5218 [details] Script reproducing the issue When dynamically loading a library along with several dependencies, calls to _dl_add_to_slotinfo and _dl_update_slotinfo can become intermixed. As a consequence, _dl_update_slotinfo will update the generation counter of the dtv although not all of the slots belonging to that generation have been added. Subsequent calls to _dl_add_to_slotinfo will add more slots to the same generation, for which no storage will be allocated, as the dtv generation checks will claim no work is necessary. This will lead to uninitialized dtv entries and will likely cause a SIGSEGV when thread local variables are accessed. The attached script, when executed in an empty directory on a GNU/Linux x86_64 system, and probably under other circumstances as well, will demonstrate the problem. It will print ./demo &tbaz=(nil) glibc-tls-bug.sh: line 75: 1752 Segmentation fault "$@" where you see that the address of the thread local variable tbaz is NULL, and the referencing that variable causes a segmentation fault.
Created attachment 5219 [details] Do update_slotinfo after add_to_slotinfo This patch fixes the issue for me. It should be reasonably safe to apply.
Cross references with further details: https://github.com/cschwan/sage-on-gentoo/issues/#issue/40 http://bugs.gentoo.org/show_bug.cgi?id=353224
I can't seem to run your test program, which I saved as "glibtest" drkirkby@hawk:~/glibc$ ./glibtest gcc -Wall -ggdb -O0 -Wl,-rpath,$ORIGIN -fPIC -shared -o ./libbar.so bar.c gcc -Wall -ggdb -O0 -Wl,-rpath,$ORIGIN -fPIC -shared -o ./libbaz.so baz.c gcc -Wall -ggdb -O0 -Wl,-rpath,$ORIGIN -fPIC -shared -o ./libfoo.so foo.c -L. -lbar -lbaz gcc -Wall -ggdb -O0 -Wl,-rpath,$ORIGIN -o demo demo.c -ldl ./demo Error loading libfoo.so: ld.so.1: demo: fatal: libbar.so: open failed: No such file or directory the library files are created, as I see the following files in the directory bar.c baz.c demo demo.c foo.c glibtest libbar.so libbaz.so libfoo.so I've got no idea what this ORIGIN is - I myself write scripts as POSIX files, not bash scripts, so perhaps this is something I don't even have in my version of bash drkirkby@hawk:~/glibc$ bash --version GNU bash, version 4.0.28(1)-release (i386-pc-solaris2.11) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law
(In reply to comment #3) > I can't seem to run your test program, which I saved as "glibtest" Strange. > gcc -Wall -ggdb -O0 -Wl,-rpath,$ORIGIN -o demo demo.c -ldl > ./demo > Error loading libfoo.so: ld.so.1: demo: > fatal: libbar.so: open failed: No such file or directory OK, seems this relative path thingy doesn't work for you, for some reason. Maybe try "LD_LIBRARY_PATH=$PWD ./demo" > I've got no idea what this ORIGIN is - I myself write scripts as POSIX files, > not bash scripts, so perhaps this is something I don't even have in my version > of bash This is nothing magic to the script, but instead some special value accepted by ld.so. See your ld.so(8) man page, or find it online e.g. at http://www.kernel.org/doc/man-pages/online/pages/man8/ld.so.8.html
(In reply to comment #4) > Strange. Or not so strange, if you are on OpenSolaris, as your recent activity on related bugs and the bash version message indicates. I guess -rpath=$ORIGIN is probably specific to the GNU/Linux dynamic linker.
I've applied a slightly modified version of the patch.
*** Bug 11952 has been marked as a duplicate of this bug. ***