mirror of https://gitee.com/Nocallback/glibc.git
Browse Source
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.release/2.14/master
committed by
Ulrich Drepper
8 changed files with 132 additions and 30 deletions
@ -0,0 +1,27 @@ |
|||
// BZ 12453
|
|||
#include <stdio.h> |
|||
#include <dlfcn.h> |
|||
|
|||
|
|||
static int |
|||
do_test (void) |
|||
{ |
|||
void* dl = dlopen ("tst-tls19mod1.so", RTLD_LAZY | RTLD_GLOBAL); |
|||
if (dl == NULL) |
|||
{ |
|||
printf ("Error loading tst-tls19mod1.so: %s\n", dlerror ()); |
|||
return 1; |
|||
} |
|||
|
|||
int (*fn) (void) = dlsym (dl, "foo"); |
|||
if (fn == NULL) |
|||
{ |
|||
printf("Error obtaining symbol foo\n"); |
|||
return 1; |
|||
} |
|||
|
|||
return fn (); |
|||
} |
|||
|
|||
#define TEST_FUNCTION do_test () |
|||
#include "../test-skeleton.c" |
|||
@ -0,0 +1,15 @@ |
|||
#include <stdio.h> |
|||
|
|||
extern int bar (void); |
|||
extern int baz (void); |
|||
|
|||
int |
|||
foo (void) |
|||
{ |
|||
int v1 = bar (); |
|||
int v2 = baz (); |
|||
|
|||
printf ("bar=%d, baz=%d\n", v1, v2); |
|||
|
|||
return v1 != 666 || v2 != 42; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
static int __thread tbar __attribute__ ((tls_model ("initial-exec"))) = 666; |
|||
|
|||
void |
|||
setter (int a) |
|||
{ |
|||
tbar = a; |
|||
} |
|||
|
|||
int |
|||
bar (void) |
|||
{ |
|||
return tbar; |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
#include <stdio.h> |
|||
|
|||
static int __thread tbaz __attribute__ ((tls_model ("local-dynamic"))) = 42; |
|||
|
|||
void |
|||
setter2 (int a) |
|||
{ |
|||
tbaz = a; |
|||
} |
|||
|
|||
int |
|||
baz (void) |
|||
{ |
|||
printf ("&tbaz=%p\n", &tbaz); |
|||
return tbaz; |
|||
} |
|||
Loading…
Reference in new issue