[RFC][PATCH v8 05/20] elf/dl-fini.c: Handle proxy link_map entries in the shutdown path
Adhemerval Zanella
adhemerval.zanella@linaro.org
Mon Feb 15 17:08:13 GMT 2021
On 09/02/2021 14:18, Vivek Das Mohapatra via Libc-alpha wrote:
> 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 c51becd06b..a0432b884d 100644
> --- a/elf/dl-close.c
> +++ b/elf/dl-close.c
> @@ -283,8 +283,9 @@ _dl_close_worker (struct link_map *map, bool force)
>
> /* Call its termination function. Do not do it for
> half-cooked objects. Temporarily disable exception
> - handling, so that errors are fatal. */
> - if (imap->l_init_called)
> + handling, so that errors are fatal.
> + 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,
Ok.
> @@ -360,7 +361,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. */
Ok.
> @@ -686,8 +689,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. */
Ok.
> #if DL_NNS == 1
> @@ -727,19 +732,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);
Ok.
> diff --git a/elf/dl-fini.c b/elf/dl-fini.c
> index 6dbdfe4b3e..10194488bb 100644
> --- a/elf/dl-fini.c
> +++ b/elf/dl-fini.c
> @@ -73,7 +73,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);
>
> @@ -111,7 +111,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;
>
Ok.
More information about the Libc-alpha
mailing list