This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[RFC][PATCH v3 5/6] elf/dl-fini.c: Handle proxy link_map entries in the shutdown path
When cleaning up before exit we should not call destructors or
otherwise free [most of] the contents of proxied link_map entries
since they share [most of] their contents with the LM_ID_BASE
objects to which they point.
---
elf/dl-close.c | 43 ++++++++++++++++++++++++++-----------------
elf/dl-fini.c | 6 ++++--
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/elf/dl-close.c b/elf/dl-close.c
index ecd6729704..6c706a4ae8 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -267,8 +267,9 @@ _dl_close_worker (struct link_map *map, bool force)
&& (imap->l_flags_1 & DF_1_NODELETE) == 0);
/* Call its termination function. Do not do it for
- half-cooked objects. */
- if (imap->l_init_called)
+ half-cooked objects.
+ Proxies should never have this flag set, but we double check. */
+ if (imap->l_init_called && !imap->l_proxy)
{
/* When debugging print a message first. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS,
@@ -353,7 +354,9 @@ _dl_close_worker (struct link_map *map, bool force)
one for the terminating NULL pointer. */
size_t remain = (new_list != NULL) + 1;
bool removed_any = false;
- for (size_t cnt = 0; imap->l_scope[cnt] != NULL; ++cnt)
+ for (size_t cnt = 0;
+ imap->l_scope && imap->l_scope[cnt] != NULL;
+ ++cnt)
/* This relies on l_scope[] entries being always set either
to its own l_symbolic_searchlist address, or some map's
l_searchlist address. */
@@ -676,8 +679,10 @@ _dl_close_worker (struct link_map *map, bool force)
/* We can unmap all the maps at once. We determined the
start address and length when we loaded the object and
- the `munmap' call does the rest. */
- DL_UNMAP (imap);
+ the `munmap' call does the rest. Proxies do not have
+ any segments of their own to unmap. */
+ if (!imap->l_proxy)
+ DL_UNMAP (imap);
/* Finally, unlink the data structure and free it. */
#if DL_NNS == 1
@@ -717,19 +722,23 @@ _dl_close_worker (struct link_map *map, bool force)
_dl_debug_printf ("\nfile=%s [%lu]; destroying link map\n",
imap->l_name, imap->l_ns);
- /* This name always is allocated. */
- free (imap->l_name);
- /* Remove the list with all the names of the shared object. */
+ /* Skip structures borrowed by proxies from the real map. */
+ if (!imap->l_proxy)
+ {
+ /* This name always is allocated. */
+ free (imap->l_name);
+ /* Remove the list with all the names of the shared object. */
- struct libname_list *lnp = imap->l_libname;
- do
- {
- struct libname_list *this = lnp;
- lnp = lnp->next;
- if (!this->dont_free)
- free (this);
- }
- while (lnp != NULL);
+ struct libname_list *lnp = imap->l_libname;
+ do
+ {
+ struct libname_list *this = lnp;
+ lnp = lnp->next;
+ if (!this->dont_free)
+ free (this);
+ }
+ while (lnp != NULL);
+ }
/* Remove the searchlists. */
free (imap->l_initfini);
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 3cfc262400..0403f6c4d8 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -72,7 +72,7 @@ _dl_fini (void)
assert (nloaded != 0 || GL(dl_ns)[ns]._ns_loaded == NULL);
for (l = GL(dl_ns)[ns]._ns_loaded, i = 0; l != NULL; l = l->l_next)
/* Do not handle ld.so in secondary namespaces. */
- if (l == l->l_real)
+ if (l == l->l_real || l->l_proxy)
{
assert (i < nloaded);
@@ -110,7 +110,9 @@ _dl_fini (void)
{
struct link_map *l = maps[i];
- if (l->l_init_called)
+ /* Do not call fini functions via proxies, or for
+ objects which are not marked as initialised. */
+ if (l->l_init_called && !l->l_proxy)
{
/* Make sure nothing happens if we are called twice. */
l->l_init_called = 0;
--
2.11.0