Bug 12453

Summary: Broken thread local storage (TLS) initialization
Product: glibc Reporter: Martin von Gagern <Martin.vGagern>
Component: libcAssignee: Ulrich Drepper <drepper.fsp>
Status: RESOLVED FIXED    
Severity: critical CC: david.kirkby, ppluzhnikov
Priority: P2 Flags: fweimer: security-
Version: 2.12   
Target Milestone: ---   
URL: http://sourceware.org/git/?p=glibc.git;a=blob;f=elf/dl-open.c;h=cf8e8cc6715f9f44b3d5d88ee4cc9b709cb37226;hb=3a33e487eeb65e2f1f633581c56bee2c60d0ca43#l417
See Also: http://bugs.gentoo.org/show_bug.cgi?id=353224
Host: Target:
Build: Last reconfirmed:
Attachments: Script reproducing the issue
Do update_slotinfo after add_to_slotinfo

Description Martin von Gagern 2011-01-30 15:14:20 UTC
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.
Comment 1 Martin von Gagern 2011-01-30 15:16:39 UTC
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.
Comment 2 Martin von Gagern 2011-01-30 18:10:54 UTC
Cross references with further details:
https://github.com/cschwan/sage-on-gentoo/issues/#issue/40
http://bugs.gentoo.org/show_bug.cgi?id=353224
Comment 3 David Kirkby 2011-04-03 03:09:27 UTC
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
Comment 4 Martin von Gagern 2011-04-03 07:24:08 UTC
(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
Comment 5 Martin von Gagern 2011-04-03 08:41:03 UTC
(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.
Comment 6 Ulrich Drepper 2011-05-15 01:27:00 UTC
I've applied a slightly modified version of the patch.
Comment 7 Ulrich Drepper 2011-05-15 01:33:07 UTC
*** Bug 11952 has been marked as a duplicate of this bug. ***