mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-26 23:10:06 +00:00
BZ #16613: Support TLS in audit libraries.
This commit fixes a bug where the dynamic loader would crash when loading audit libraries, via LD_AUDIT, where those libraries used TLS. The dynamic loader was not considering that the audit libraries would use TLS and failed to bump the TLS generation counter leaving TLS usage inconsistent after loading the audit libraries. https://sourceware.org/ml/libc-alpha/2014-02/msg00569.html
This commit is contained in:
parent
4cbf380ce9
commit
d050367659
14
ChangeLog
14
ChangeLog
@ -1,3 +1,17 @@
|
||||
2014-02-25 Ulrich Drepper <drepper@gmail.com>
|
||||
Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
[BZ #16613]
|
||||
* elf/dl-tls.c (_dl_count_modids): New function.
|
||||
* sysdeps/generic/ldsodefs.h: Declare _dl_count_modids.
|
||||
* elf/rtld.c (dl_main): Call _dl_count_modids to track TLS usage in
|
||||
audit library and increment generation counter.
|
||||
(_dl_allocate_tls_init): Add assertion to check TLS generation count.
|
||||
* elf/tst-audit9.c: New file.
|
||||
* elf/tst-auditmod9a.c: New file.
|
||||
* elf/tst-auditmod9b.c: New file.
|
||||
* elf/Makefile: Add rules to build and run tst-audit9.
|
||||
|
||||
2014-02-25 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
[BZ #15347]
|
||||
|
3
NEWS
3
NEWS
@ -9,7 +9,8 @@ Version 2.20
|
||||
|
||||
* The following bugs are resolved with this release:
|
||||
|
||||
15347, 15804, 15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611.
|
||||
15347, 15804, 15894, 16447, 16545, 16574, 16600, 16609, 16610, 16611,
|
||||
16613.
|
||||
|
||||
* The am33 port, which had not worked for several years, has been removed
|
||||
from ports.
|
||||
|
@ -144,7 +144,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
|
||||
tst-dlmodcount tst-dlopenrpath tst-deep1 \
|
||||
tst-dlmopen1 tst-dlmopen2 tst-dlmopen3 \
|
||||
unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
|
||||
tst-audit1 tst-audit2 tst-audit8 \
|
||||
tst-audit1 tst-audit2 tst-audit8 tst-audit9 \
|
||||
tst-stackguard1 tst-addr1 tst-thrlock \
|
||||
tst-unique1 tst-unique2 tst-unique3 tst-unique4 \
|
||||
tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
|
||||
@ -203,6 +203,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
||||
order2mod1 order2mod2 order2mod3 order2mod4 \
|
||||
tst-unique1mod1 tst-unique1mod2 \
|
||||
tst-unique2mod1 tst-unique2mod2 \
|
||||
tst-auditmod9a tst-auditmod9b \
|
||||
tst-unique3lib tst-unique3lib2 \
|
||||
tst-unique4lib \
|
||||
tst-initordera1 tst-initorderb1 \
|
||||
@ -560,6 +561,8 @@ unload4mod1.so-no-z-defs = yes
|
||||
ifuncmod1.so-no-z-defs = yes
|
||||
ifuncmod5.so-no-z-defs = yes
|
||||
ifuncmod6.so-no-z-defs = yes
|
||||
tst-auditmod9a.so-no-z-defs = yes
|
||||
tst-auditmod9b.so-no-z-defs = yes
|
||||
|
||||
ifeq ($(build-shared),yes)
|
||||
# Build all the modules even when not actually running test programs.
|
||||
@ -1012,6 +1015,10 @@ tst-audit1-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
|
||||
$(objpfx)tst-audit2.out: $(objpfx)tst-auditmod1.so
|
||||
tst-audit2-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
|
||||
|
||||
$(objpfx)tst-audit9: $(libdl)
|
||||
$(objpfx)tst-audit9.out: $(objpfx)tst-auditmod9a.so $(objpfx)tst-auditmod9b.so
|
||||
tst-audit9-ENV = LD_AUDIT=$(objpfx)tst-auditmod9a.so
|
||||
|
||||
$(objpfx)tst-audit8: $(common-objpfx)math/libm.so
|
||||
$(objpfx)tst-audit8.out: $(objpfx)tst-auditmod1.so
|
||||
tst-audit8-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
|
||||
|
28
elf/dl-tls.c
28
elf/dl-tls.c
@ -105,6 +105,33 @@ _dl_next_tls_modid (void)
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
internal_function
|
||||
_dl_count_modids (void)
|
||||
{
|
||||
/* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
|
||||
we fail to load a module and unload it leaving a gap. If we don't
|
||||
have gaps then the number of modids is the current maximum so
|
||||
return that. */
|
||||
if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
|
||||
return GL(dl_tls_max_dtv_idx);
|
||||
|
||||
/* We have gaps and are forced to count the non-NULL entries. */
|
||||
size_t n = 0;
|
||||
struct dtv_slotinfo_list *runp = GL(dl_tls_dtv_slotinfo_list);
|
||||
while (runp != NULL)
|
||||
{
|
||||
for (size_t i = 0; i < runp->len; ++i)
|
||||
if (runp->slotinfo[i].map != NULL)
|
||||
++n;
|
||||
|
||||
runp = runp->next;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
#ifdef SHARED
|
||||
void
|
||||
internal_function
|
||||
@ -407,6 +434,7 @@ _dl_allocate_tls_init (void *result)
|
||||
|
||||
/* Keep track of the maximum generation number. This might
|
||||
not be the generation counter. */
|
||||
assert (listp->slotinfo[cnt].gen <= GL(dl_tls_generation));
|
||||
maxgen = MAX (maxgen, listp->slotinfo[cnt].gen);
|
||||
|
||||
if (map->l_tls_offset == NO_TLS_OFFSET
|
||||
|
@ -1569,6 +1569,10 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
}
|
||||
}
|
||||
|
||||
/* Keep track of the currently loaded modules to count how many
|
||||
non-audit modules which use TLS are loaded. */
|
||||
size_t count_modids = _dl_count_modids ();
|
||||
|
||||
/* Set up debugging before the debugger is notified for the first time. */
|
||||
#ifdef ELF_MACHINE_DEBUG_SETUP
|
||||
/* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */
|
||||
@ -2220,7 +2224,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
|
||||
_dl_start_profile ();
|
||||
}
|
||||
|
||||
if (!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
|
||||
if ((!was_tls_init_tp_called && GL(dl_tls_max_dtv_idx) > 0)
|
||||
|| count_modids != _dl_count_modids ())
|
||||
++GL(dl_tls_generation);
|
||||
|
||||
/* Now that we have completed relocation, the initializer data
|
||||
|
8
elf/tst-audit9.c
Normal file
8
elf/tst-audit9.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <dlfcn.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
void *h = dlopen("$ORIGIN/tst-auditmod9b.so", RTLD_LAZY);
|
||||
int (*fp)(void) = dlsym(h, "f");
|
||||
return fp() - 1;
|
||||
}
|
15
elf/tst-auditmod9a.c
Normal file
15
elf/tst-auditmod9a.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdint.h>
|
||||
|
||||
__thread int var;
|
||||
|
||||
unsigned int
|
||||
la_version (unsigned int v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
la_activity (uintptr_t *cookie, unsigned int flag)
|
||||
{
|
||||
++var;
|
||||
}
|
6
elf/tst-auditmod9b.c
Normal file
6
elf/tst-auditmod9b.c
Normal file
@ -0,0 +1,6 @@
|
||||
__thread int a;
|
||||
|
||||
int f(void)
|
||||
{
|
||||
return ++a;
|
||||
}
|
@ -957,6 +957,9 @@ extern void _dl_sysdep_start_cleanup (void)
|
||||
/* Determine next available module ID. */
|
||||
extern size_t _dl_next_tls_modid (void) internal_function attribute_hidden;
|
||||
|
||||
/* Count the modules with TLS segments. */
|
||||
extern size_t _dl_count_modids (void) internal_function attribute_hidden;
|
||||
|
||||
/* Calculate offset of the TLS blocks in the static TLS block. */
|
||||
extern void _dl_determine_tlsoffset (void) internal_function attribute_hidden;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user