|
|
548bcb |
commit 572bd547d57a39b6cf0ea072545dc4048921f4c3
|
|
|
548bcb |
Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
|
|
|
548bcb |
Date: Thu Dec 31 13:59:38 2020 +0000
|
|
|
548bcb |
|
|
|
548bcb |
elf: Fix DTV gap reuse logic [BZ #27135]
|
|
|
548bcb |
|
|
|
548bcb |
For some reason only dlopen failure caused dtv gaps to be reused.
|
|
|
548bcb |
|
|
|
548bcb |
It is possible that the intent was to never reuse modids for a
|
|
|
548bcb |
different module, but after dlopen failure all gaps are reused
|
|
|
548bcb |
not just the ones caused by the unfinished dlopened.
|
|
|
548bcb |
|
|
|
548bcb |
So the code has to handle reused modids already which seems to
|
|
|
548bcb |
work, however the data races at thread creation and tls access
|
|
|
548bcb |
(see bug 19329 and bug 27111) may be more severe if slots are
|
|
|
548bcb |
reused so this is scheduled after those fixes. I think fixing
|
|
|
548bcb |
the races are not simpler if reuse is disallowed and reuse has
|
|
|
548bcb |
other benefits, so set GL(dl_tls_dtv_gaps) whenever entries are
|
|
|
548bcb |
removed from the middle of the slotinfo list. The value does
|
|
|
548bcb |
not have to be correct: incorrect true value causes the next
|
|
|
548bcb |
modid query to do a slotinfo walk, incorrect false will leave
|
|
|
548bcb |
gaps and new entries are added at the end.
|
|
|
548bcb |
|
|
|
548bcb |
Fixes bug 27135.
|
|
|
548bcb |
|
|
|
548bcb |
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
|
|
548bcb |
|
|
|
548bcb |
diff --git a/elf/dl-close.c b/elf/dl-close.c
|
|
|
548bcb |
index 7d2dc2272cd643f5..41cb6c58491c364b 100644
|
|
|
548bcb |
--- a/elf/dl-close.c
|
|
|
548bcb |
+++ b/elf/dl-close.c
|
|
|
548bcb |
@@ -88,7 +88,11 @@ remove_slotinfo (size_t idx, struct dtv_slotinfo_list *listp, size_t disp,
|
|
|
548bcb |
/* If this is not the last currently used entry no need to look
|
|
|
548bcb |
further. */
|
|
|
548bcb |
if (idx != GL(dl_tls_max_dtv_idx))
|
|
|
548bcb |
- return true;
|
|
|
548bcb |
+ {
|
|
|
548bcb |
+ /* There is an unused dtv entry in the middle. */
|
|
|
548bcb |
+ GL(dl_tls_dtv_gaps) = true;
|
|
|
548bcb |
+ return true;
|
|
|
548bcb |
+ }
|
|
|
548bcb |
}
|
|
|
548bcb |
|
|
|
548bcb |
while (idx - disp > (disp == 0 ? 1 + GL(dl_tls_static_nelem) : 0))
|
|
|
548bcb |
diff --git a/elf/dl-open.c b/elf/dl-open.c
|
|
|
548bcb |
index a67fb3aee40860e1..54727402750f4c0c 100644
|
|
|
548bcb |
--- a/elf/dl-open.c
|
|
|
548bcb |
+++ b/elf/dl-open.c
|
|
|
548bcb |
@@ -896,16 +896,6 @@ no more namespaces available for dlmopen()"));
|
|
|
548bcb |
state if relocation failed, for example. */
|
|
|
548bcb |
if (args.map)
|
|
|
548bcb |
{
|
|
|
548bcb |
- /* Maybe some of the modules which were loaded use TLS.
|
|
|
548bcb |
- Since it will be removed in the following _dl_close call
|
|
|
548bcb |
- we have to mark the dtv array as having gaps to fill the
|
|
|
548bcb |
- holes. This is a pessimistic assumption which won't hurt
|
|
|
548bcb |
- if not true. There is no need to do this when we are
|
|
|
548bcb |
- loading the auditing DSOs since TLS has not yet been set
|
|
|
548bcb |
- up. */
|
|
|
548bcb |
- if ((mode & __RTLD_AUDIT) == 0)
|
|
|
548bcb |
- GL(dl_tls_dtv_gaps) = true;
|
|
|
548bcb |
-
|
|
|
548bcb |
_dl_close_worker (args.map, true);
|
|
|
548bcb |
|
|
|
548bcb |
/* All l_nodelete_pending objects should have been deleted
|
|
|
548bcb |
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
|
|
|
548bcb |
index 801eafad3961573c..bacb4101e2e2c4e5 100644
|
|
|
548bcb |
--- a/elf/dl-tls.c
|
|
|
548bcb |
+++ b/elf/dl-tls.c
|
|
|
548bcb |
@@ -187,10 +187,7 @@ _dl_next_tls_modid (void)
|
|
|
548bcb |
size_t
|
|
|
548bcb |
_dl_count_modids (void)
|
|
|
548bcb |
{
|
|
|
548bcb |
- /* It is rare that we have gaps; see elf/dl-open.c (_dl_open) where
|
|
|
548bcb |
- we fail to load a module and unload it leaving a gap. If we don't
|
|
|
548bcb |
- have gaps then the number of modids is the current maximum so
|
|
|
548bcb |
- return that. */
|
|
|
548bcb |
+ /* The count is the max unless dlclose or failed dlopen created gaps. */
|
|
|
548bcb |
if (__glibc_likely (!GL(dl_tls_dtv_gaps)))
|
|
|
548bcb |
return GL(dl_tls_max_dtv_idx);
|
|
|
548bcb |
|