From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27449 invoked by alias); 31 Oct 2008 20:11:41 -0000 Received: (qmail 27398 invoked by uid 22791); 31 Oct 2008 20:11:40 -0000 X-Spam-Check-By: sourceware.org Received: from sunsite.ms.mff.cuni.cz (HELO sunsite.mff.cuni.cz) (195.113.15.26) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 31 Oct 2008 20:11:08 +0000 Received: from sunsite.mff.cuni.cz (localhost.localdomain [127.0.0.1]) by sunsite.mff.cuni.cz (8.13.8/8.13.8) with ESMTP id m9VKG2Ae022670; Fri, 31 Oct 2008 21:16:02 +0100 Received: (from jakub@localhost) by sunsite.mff.cuni.cz (8.13.8/8.13.8/Submit) id m9VKG1s0022669; Fri, 31 Oct 2008 21:16:02 +0100 Date: Fri, 31 Oct 2008 20:11:00 -0000 From: Jakub Jelinek To: Ulrich Drepper Cc: Glibc hackers Subject: [PATCH] Fix __tls_get_addr Message-ID: <20081031201601.GG32107@sunsite.ms.mff.cuni.cz> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4.2.2i Mailing-List: contact libc-hacker-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-hacker-owner@sourceware.org X-SW-Source: 2008-10/txt/msg00005.txt.bz2 Hi! As can be seen on the attached testcase, _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). 2008-10-31 Jakub Jelinek * elf/dl-tls.c (__tls_get_addr): After calling _dl_update_slotinfo refetch dtv, as it might have changed. * elf/Makefile: Add rules to build and run tst-tls18. * elf/tst-tls18.c: New test. * elf/tst-tlsmod18a.c: New file. --- libc/elf/dl-tls.c.jj 2008-10-17 12:11:10.000000000 +0200 +++ libc/elf/dl-tls.c 2008-10-31 20:36:14.000000000 +0100 @@ -756,7 +756,10 @@ __tls_get_addr (GET_ADDR_ARGS) void *p; if (__builtin_expect (dtv[0].counter != GL(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; --- libc/elf/Makefile.jj 2008-10-24 11:42:12.000000000 +0200 +++ libc/elf/Makefile 2008-10-31 20:46:09.000000000 +0100 @@ -166,7 +166,7 @@ tests += loadtest restest1 preloadtest l restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \ tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \ - tst-tls16 tst-tls17 tst-tls-dlinfo \ + tst-tls16 tst-tls17 tst-tls18 tst-tls-dlinfo \ tst-align tst-align2 $(tests-execstack-$(have-z-execstack)) \ tst-dlmodcount tst-dlopenrpath tst-deep1 \ tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \ @@ -182,6 +182,7 @@ tests: $(objpfx)tst-pie1.out endif tests: $(objpfx)tst-leaks1-mem 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 modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \ testobj1_1 failobj constload2 constload3 unloadmod \ dep1 dep2 dep3 dep4 vismod1 vismod2 vismod3 \ @@ -203,6 +204,7 @@ modules-names = testobj1 testobj2 testob tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \ $(patsubst %,tst-tlsmod17a%,$(tlsmod17a-suffixes)) \ tst-tlsmod17b \ + $(patsubst %,tst-tlsmod18a%,$(tlsmod18a-suffixes)) \ circlemod1 circlemod1a circlemod2 circlemod2a \ circlemod3 circlemod3a \ reldep8mod1 reldep8mod2 reldep8mod3 \ @@ -724,6 +726,12 @@ $(patsubst %,$(objpfx)tst-tlsmod17a%.os, $(patsubst %,$(objpfx)tst-tlsmod17a%.so,$(tlsmod17a-suffixes)): $(objpfx)tst-tlsmod17a%.so: $(objpfx)ld.so $(objpfx)tst-tlsmod17b.so: $(patsubst %,$(objpfx)tst-tlsmod17a%.so,$(tlsmod17a-suffixes)) +$(objpfx)tst-tls18: $(libdl) +$(objpfx)tst-tls18.out: $(patsubst %,$(objpfx)tst-tlsmod18a%.so,$(tlsmod18a-suffixes)) +$(patsubst %,$(objpfx)tst-tlsmod18a%.os,$(tlsmod18a-suffixes)): $(objpfx)tst-tlsmod18a%.os : tst-tlsmod18a.c + $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ -DN=$* -DNOT_IN_libc=1 $< +$(patsubst %,$(objpfx)tst-tlsmod18a%.so,$(tlsmod18a-suffixes)): $(objpfx)tst-tlsmod18a%.so: $(objpfx)ld.so + CFLAGS-tst-align.c = $(stack-align-test-flags) CFLAGS-tst-align2.c = $(stack-align-test-flags) CFLAGS-tst-alignmod.c = $(stack-align-test-flags) --- libc/elf/tst-tls18.c.jj 2008-10-31 20:47:20.000000000 +0100 +++ libc/elf/tst-tls18.c 2008-10-31 20:51:50.000000000 +0100 @@ -0,0 +1,37 @@ +#include +#include + +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" --- libc/elf/tst-tlsmod18a.c.jj 2008-10-31 20:52:04.000000000 +0100 +++ libc/elf/tst-tlsmod18a.c 2008-10-31 20:53:01.000000000 +0100 @@ -0,0 +1,21 @@ +#include + +#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; +} Jakub