diff options
author | Carmelo Amoroso <carmelo.amoroso@st.com> | 2009-12-03 13:33:16 +0100 |
---|---|---|
committer | Carmelo Amoroso <carmelo.amoroso@st.com> | 2009-12-03 13:33:16 +0100 |
commit | b3d31460fbf188997c7337296a61409529f7c974 (patch) | |
tree | b451066b5b869f1d6941d5232ba4f97ad8e56c00 | |
parent | b93ab6041d56a5a19d8a97b69f6e3202fd11e859 (diff) |
ldso_tls: Refetch dtv from memory if THREAD_DTV has changed
_dl_update_slotinfo might change THREAD_DTV () (if it needs to reallocate it),
but the caller (__tls_get_addr) doesn't refetch dtv from memory, it uses its
cached copy. This may crash (if dtv[GET_ADDR_MODULE] is off the cliff, or
might read uninitialized memory and return it.
Typically dtv[GET_ADDR_MODULE].pointer.val is NULL and so __tls_get_addr
returns NULL + offset_within_PT_TLS. The next time __tls_get_addr is called
for the same library it will return correct address as _dl_update_slotinfo
won't need to be called.
Signed-off-by: Jakub Jelinek <jakub@redhat.com>
Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com>
Signed-off-by: Carmelo Amoroso <carmelo.amoroso@st.com>
-rw-r--r-- | ldso/ldso/dl-tls.c | 5 | ||||
-rw-r--r-- | test/tls/Makefile.in | 11 | ||||
-rw-r--r-- | test/tls/tst-tls18.c | 38 | ||||
-rw-r--r-- | test/tls/tst-tlsmod18a.c | 21 |
4 files changed, 73 insertions, 2 deletions
diff --git a/ldso/ldso/dl-tls.c b/ldso/ldso/dl-tls.c index 52b7aa534..d2808f968 100644 --- a/ldso/ldso/dl-tls.c +++ b/ldso/ldso/dl-tls.c @@ -842,7 +842,10 @@ __tls_get_addr (GET_ADDR_ARGS) void *p; if (__builtin_expect (dtv[0].counter != _dl_tls_generation, 0)) - the_map = _dl_update_slotinfo (GET_ADDR_MODULE); + { + the_map = _dl_update_slotinfo (GET_ADDR_MODULE); + dtv = THREAD_DTV (); + } p = dtv[GET_ADDR_MODULE].pointer.val; diff --git a/test/tls/Makefile.in b/test/tls/Makefile.in index 082ab1cd0..69a8eaf27 100644 --- a/test/tls/Makefile.in +++ b/test/tls/Makefile.in @@ -3,7 +3,7 @@ TESTS := tst-tls1 tst-tls2 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 \ tst-tls8 tst-tls9 tst-tls10 tst-tls11 tst-tls12 tst-tls13 \ - tst-tls14 tst-tls15 tst-tls16 tst-tls17 tst-tls-at-ctor \ + tst-tls14 tst-tls15 tst-tls16 tst-tls17 tst-tls18 tst-tls-at-ctor \ tst-tls1-static tst-tls2-static tst-tls9-static TESTS_DISABLED := tst-tls1-static tst-tls2-static tst-tls9-static @@ -27,6 +27,7 @@ EXTRA_CFLAGS := -DNOT_IN_libc=1 \ -include $(top_builddir)include/libc-symbols.h tlsmod17a-suffixes := 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +tlsmod18a-suffixes := 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 CFLAGS_tst-tlsmod1.so := -fPIC -DSHARED -shared CFLAGS_tst-tlsmod2.so := -fPIC -DSHARED -shared CFLAGS_tst-tlsmod3.so := -fPIC -DSHARED -shared @@ -49,6 +50,7 @@ CFLAGS_tst-tlsmod16a.so := -fPIC -DSHARED -shared CFLAGS_tst-tlsmod16b.so := -fPIC -DSHARED -shared CFLAGS_tst-tlsmod17a.so := -fPIC -DSHARED -shared CFLAGS_tst-tlsmod17b.so := -fPIC -DSHARED -shared +CFLAGS_tst-tlsmod18a.so := -fPIC -DSHARED -shared CFLAGS_tst-tlsmod-at-ctor.so := -fPIC -DSHARED -shared LDFLAGS_tst-tlsmod1.so := -shared -static-libgcc -L$(top_builddir)lib @@ -80,6 +82,7 @@ LDFLAGS_tst-tlsmod16b.so := -shared -static-libgcc -L$(top_builddir)lib LDFLAGS_tst-tlsmod17a.so := -shared -static-libgcc -L$(top_builddir)lib LDFLAGS_tst-tlsmod17b.so := -shared -static-libgcc -L$(top_builddir)lib \ $(patsubst %,tst-tlsmod17a%.so,$(tlsmod17a-suffixes)) +LDFLAGS_tst-tlsmod18a.so := -shared -static-libgcc -L$(top_builddir)lib LDFLAGS_tst-tlsmod-at-ctor.so := -shared -static-libgcc -L$(top_builddir)lib LDFLAGS_tst-tls3 := tst-tlsmod1.so tst-tlsmod4.so @@ -97,6 +100,7 @@ LDFLAGS_tst-tls14 := -ldl -Wl,-rpath-link=. tst-tlsmod14a.so LDFLAGS_tst-tls15 := -ldl -Wl,-rpath-link=. LDFLAGS_tst-tls16 := -ldl -Wl,-rpath-link=. LDFLAGS_tst-tls17 := -ldl -Wl,-rpath-link=. +LDFLAGS_tst-tls18 := -ldl -Wl,-rpath-link=. LDFLAGS_tst-tls-at-ctor := tst-tlsmod-at-ctor.so tst-tls3: tst-tlsmod1.so tst-tlsmod4.so @@ -119,6 +123,11 @@ tst-tlsmod17a%.so: tst-tlsmod17a.c $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_tst-tlsmod17a.so) $< -o $@ \ -DN=$* -Wl,-soname,$@ $(LDFLAGS) $(EXTRA_LIBS) \ $(LDFLAGS_tst-tlsmod17a.so) +tst-tls18: $(patsubst %,tst-tlsmod18a%.so,$(tlsmod18a-suffixes)) +tst-tlsmod18a%.so: tst-tlsmod18a.c + $(Q)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_tst-tlsmod18a.so) $< -o $@ \ + -DN=$* -Wl,-soname,$@ $(LDFLAGS) $(EXTRA_LIBS) \ + $(LDFLAGS_tst-tlsmod18a.so) tst-tls-at-ctor: tst-tlsmod-at-ctor.so RET_tst-tls13 := 1 diff --git a/test/tls/tst-tls18.c b/test/tls/tst-tls18.c new file mode 100644 index 000000000..00dcdff4e --- /dev/null +++ b/test/tls/tst-tls18.c @@ -0,0 +1,38 @@ +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> + +static int +do_test (void) +{ + char modname[sizeof "tst-tlsmod18aXX.so"]; + void *h[20]; + for (int i = 0; i < 20; i++) + { + snprintf (modname, sizeof modname, "tst-tlsmod18a%d.so", i); + h[i] = dlopen (modname, RTLD_LAZY); + if (h[i] == NULL) + { + printf ("unexpectedly failed to open %s", modname); + exit (1); + } + } + + for (int i = 0; i < 20; i++) + { + int (*fp) (void) = (int (*) (void)) dlsym (h[i], "test"); + if (fp == NULL) + { + printf ("cannot find test in tst-tlsmod18a%d.so", i); + exit (1); + } + + if (fp ()) + exit (1); + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/test/tls/tst-tlsmod18a.c b/test/tls/tst-tlsmod18a.c new file mode 100644 index 000000000..9aba607ed --- /dev/null +++ b/test/tls/tst-tlsmod18a.c @@ -0,0 +1,21 @@ +#include <stdio.h> + +#ifndef N +# define N 0 +#endif + +static __thread int var = 4; + +int +test (void) +{ + int *p = &var; + /* GCC assumes &var is never NULL, add optimization barrier. */ + __asm __volatile ("" : "+r" (p)); + if (p == NULL || *p != 4) + { + printf ("fail %d %p\n", N, p); + return 1; + } + return 0; +} |