public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Carlos O'Donell <carlos@redhat.com>
To: "Vivek Das Mohapatra" <vivek@collabora.com>, libc-alpha@sourceware.org
Cc: "Vivek Das Mohapatra" <vivek@collabora.co.uk>
Subject: Re: [RFC][PATCH v1 5/5] elf/dl-fini.c: Handle cloned link_map entries in the shutdown path
Date: Fri, 18 May 2018 19:09:00 -0000	[thread overview]
Message-ID: <9f6457e7-f42e-bad3-2d88-1bdb99823c60@redhat.com> (raw)
In-Reply-To: <20180516171124.24962-6-vivek@collabora.com>

On 05/16/2018 01:11 PM, Vivek Das Mohapatra wrote:
> From: Vivek Das Mohapatra <vivek@collabora.co.uk>
> 
> When cleaning up before exit we should not call destructors or
> otherwise free [most of] the contents of a cloned link_map entry
> since they share [most of] their contents with the LM_ID_BASE
> object from which they were cloned.

s/clones/proxies/g

> Instead we do the minimal cleanup necessary and remove them from
> the namespace linked list(s) before the main cleanup code path
> is triggered: This prevemts double-frees and double-invocation
> of any destructors (which might not be idempotent).
> ---
>  elf/dl-fini.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/elf/dl-fini.c b/elf/dl-fini.c
> index 3cfc262400..643a68504e 100644
> --- a/elf/dl-fini.c
> +++ b/elf/dl-fini.c
> @@ -24,6 +24,50 @@
>  /* Type of the constructor functions.  */
>  typedef void (*fini_t) (void);
>  
> +/* Remove (and free) cloned entries from the namespace specifid by `ns'.  */
> +void
> +_dl_forget_clones (Lmid_t ns)
> +{
> +#ifdef SHARED /* Obviously none of this applies if */

Move the #ifdef up to the caller please.

> +  struct link_map *clone;
> +  struct link_map *next;
> +
> +  if (ns < 0 || ns >= DL_NNS)
> +    return;

Make this an assert. It is an internal error to have an invalid ns at 
this point. We should not return and ignore this.

> +
> +  for (clone = GL(dl_ns)[ns]._ns_loaded; clone != NULL; clone = next)
> +    {
> +      next = clone->l_next;
> +
> +      /* Not actually clone, don't care.  */
> +      if (!clone->l_clone)
> +        continue;
> +
> +      if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
> +        _dl_debug_printf ("\nclone removed %s [%lu]\n", clone->l_name, ns);
> +
> +      /* If item is a clone, slice it out of the linked list.  */
> +      if (clone == GL(dl_ns)[ns]._ns_loaded)
> +        GL(dl_ns)[ns]._ns_loaded = clone->l_next;
> +      else
> +        clone->l_prev->l_next = clone->l_next;
> +
> +      /* Remember to fix up the links in both directions.  */
> +      if (clone->l_next)
> +        clone->l_next->l_prev = clone->l_prev;
> +
> +      /* Don't need to do most destructor handling for clones.  */
> +      if (clone->l_free_initfini)
> +        free (clone->l_initfini);
> +
> +      /* Do need to fix the global load count which is updated in
> +         _dl_add_to_namespace_list.  */
> +      GL(dl_ns)[ns]._ns_nloaded--;
> +
> +      free (clone);
> +    }
> +#endif
> +}

OK.
  
>  void
>  _dl_fini (void)
> @@ -52,6 +96,12 @@ _dl_fini (void)
>        /* Protect against concurrent loads and unloads.  */
>        __rtld_lock_lock_recursive (GL(dl_load_lock));
>  
> +      /* We need to remove any pointers to cloned entries (link_map
> +         structs that are copied from one namespace to another to
> +         implement RTLD_SHARED semantics) before the regular cleanup
> +         code gets to them.  */
> +      _dl_forget_clones (ns);

While this is easy to implement like this, I think we are going to run
into use cases where this doesn't work.

Consider this test case:

- Only a fini in a library.
- Lazy binding.
- fini calls a libc.so.6 function for the first time.
- When fini is called we jump into ld.so to find the symbol to call,
  but the libc.so.6 proxy has been removed, and so we can no longer
  resolve calls to it.

You will, IMO, have to remove the proxies at the point the library
would have been unloaded normally from the namespace, but avoid doing
all the other work.

> +
>        unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
>        /* No need to do anything for empty namespaces or those used for
>  	 auditing DSOs.  */
> 

In summary I think we need a v2 of this patch which implements a more complex
free-at-unload support.

-- 
Cheers,
Carlos.

  reply	other threads:[~2018-05-18 19:09 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-16 17:11 [RFC][PATCH v1 0/5] Proof-of-Concept implementation of RTLD_SHARED for dlmopen Vivek Das Mohapatra
2018-05-16 17:11 ` [RFC][PATCH v1 2/5] include/link.h: Update the link_map struct to allow clones Vivek Das Mohapatra
2018-05-18 18:47   ` Carlos O'Donell
2018-05-18 19:32     ` Vivek Das Mohapatra
2018-05-16 17:11 ` [RFC][PATCH v1 5/5] elf/dl-fini.c: Handle cloned link_map entries in the shutdown path Vivek Das Mohapatra
2018-05-18 19:09   ` Carlos O'Donell [this message]
2018-05-18 19:25     ` Vivek Das Mohapatra
2018-05-16 17:11 ` [RFC][PATCH v1 3/5] elf/dl-object.c: Implement a helper function to clone link_map entries Vivek Das Mohapatra
2018-05-20  2:48   ` Carlos O'Donell
2018-05-16 17:11 ` [RFC][PATCH v1 1/5] bits/dlfcn.h: Declare and describe the dlmopen RTLD_SHARED flag Vivek Das Mohapatra
2018-05-18 18:37   ` Carlos O'Donell
2018-05-18 19:31     ` Vivek Das Mohapatra
2018-05-16 17:19 ` [RFC][PATCH v1 4/5] elf/dl-load.c, elf-dl-open.c: Implement RTLD_SHARED dlmopen cloning Vivek Das Mohapatra
2018-05-18 19:02   ` Carlos O'Donell
2018-05-18 19:20     ` Vivek Das Mohapatra
2018-05-16 19:30 ` [RFC][PATCH v1 0/5] Proof-of-Concept implementation of RTLD_SHARED for dlmopen Joseph Myers
2018-05-16 19:39   ` Vivek Das Mohapatra
2018-05-16 19:44     ` Carlos O'Donell
2018-05-16 19:46       ` Vivek Das Mohapatra
2018-05-16 20:39         ` Carlos O'Donell
2018-05-18 11:46           ` Vivek Das Mohapatra
2018-05-18 18:16             ` Carlos O'Donell
2018-05-16 19:44     ` Joseph Myers
2018-05-16 19:46       ` Vivek Das Mohapatra
2018-05-16 20:03         ` Vivek Das Mohapatra
2018-05-18 18:30 ` Carlos O'Donell
2018-05-18 19:06   ` Vivek Das Mohapatra
2018-05-18 19:26     ` Carlos O'Donell
2018-05-18 19:53       ` Vivek Das Mohapatra
2018-05-18 20:03         ` Carlos O'Donell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9f6457e7-f42e-bad3-2d88-1bdb99823c60@redhat.com \
    --to=carlos@redhat.com \
    --cc=libc-alpha@sourceware.org \
    --cc=vivek@collabora.co.uk \
    --cc=vivek@collabora.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).