mirror of
git://sourceware.org/git/glibc.git
synced 2025-03-19 13:40:59 +08:00
[PR19826] fix non-LE TLS in static programs
An earlier fix for TLS dropped early initialization of DTV entries for modules using static TLS, leaving it for __tls_get_addr to set them up. That worked on platforms that require the GD access model to be relaxed to LE in the main executable, but it caused a regression on platforms that allow GD in the main executable, particularly in statically-linked programs: they use a custom __tls_get_addr that does not update the DTV, which fails when the DTV early initialization is not performed. In static programs, __libc_setup_tls performs the DTV initialization for the main thread, but the DTV of other threads is set up in _dl_allocate_tls_init, so that's the fix that matters. Restoring the initialization in the remaining functions modified by this patch was just for uniformity. It's not clear that it is ever needed: even on platforms that allow GD in the main executable, the dynamically-linked version of __tls_get_addr would set up the DTV entries, even for static TLS modules, while updating the DTV counter. for ChangeLog [BZ #19826] * elf/dl-tls.c (_dl_allocate_tls_init): Restore DTV early initialization of static TLS entries. * elf/dl-reloc.c (_dl_nothread_init_static_tls): Likewise. * nptl/allocatestack.c (init_one_static_tls): Likewise.
This commit is contained in:
parent
444eacba82
commit
17af5da98c
@ -1,3 +1,11 @@
|
||||
2016-09-21 Alexandre Oliva <aoliva@redhat.com>
|
||||
|
||||
[BZ #19826]
|
||||
* elf/dl-tls.c (_dl_allocate_tls_init): Restore DTV early
|
||||
initialization of static TLS entries.
|
||||
* elf/dl-reloc.c (_dl_nothread_init_static_tls): Likewise.
|
||||
* nptl/allocatestack.c (init_one_static_tls): Likewise.
|
||||
|
||||
2016-09-22 Samuel Thibault <samuel.thibault@ens-lyon.org>
|
||||
|
||||
* hurd/hurdmalloc.c (malloc_fork_prepare): Rename to
|
||||
|
@ -137,6 +137,12 @@ _dl_nothread_init_static_tls (struct link_map *map)
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
|
||||
/* Fill in the DTV slot so that a later LD/GD access will find it. */
|
||||
dtv_t *dtv = THREAD_DTV ();
|
||||
assert (map->l_tls_modid <= dtv[-1].counter);
|
||||
dtv[map->l_tls_modid].pointer.to_free = NULL;
|
||||
dtv[map->l_tls_modid].pointer.val = dest;
|
||||
|
||||
/* Initialize the memory. */
|
||||
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
|
||||
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
|
||||
|
@ -538,6 +538,10 @@ _dl_allocate_tls_init (void *result)
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
#endif
|
||||
|
||||
/* Set up the DTV entry. The simplified __tls_get_addr that
|
||||
some platforms use in static programs requires it. */
|
||||
dtv[map->l_tls_modid].pointer.val = dest;
|
||||
|
||||
/* Copy the initialization image and clear the BSS part. */
|
||||
memset (__mempcpy (dest, map->l_tls_initimage,
|
||||
map->l_tls_initimage_size), '\0',
|
||||
|
@ -1207,9 +1207,12 @@ init_one_static_tls (struct pthread *curp, struct link_map *map)
|
||||
# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
|
||||
# endif
|
||||
|
||||
/* We cannot delay the initialization of the Static TLS area, since
|
||||
it can be accessed with LE or IE, but since the DTV is only used
|
||||
by GD and LD, we can delay its update to avoid a race. */
|
||||
/* Fill in the DTV slot so that a later LD/GD access will find it. */
|
||||
dtv_t *dtv = GET_DTV (TLS_TPADJ (curp));
|
||||
dtv[map->l_tls_modid].pointer.to_free = NULL;
|
||||
dtv[map->l_tls_modid].pointer.val = dest;
|
||||
|
||||
/* Initialize the memory. */
|
||||
memset (__mempcpy (dest, map->l_tls_initimage, map->l_tls_initimage_size),
|
||||
'\0', map->l_tls_blocksize - map->l_tls_initimage_size);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user