[RFC,v8,13/20] Use the DSO search helper to check for preloaded DT_GNU_UNIQUE DSOs

Message ID 20210209171839.7911-14-vivek@collabora.com
State Superseded
Delegated to: Adhemerval Zanella Netto
Headers
Series Implementation of RTLD_SHARED for dlmopen |

Commit Message

Vivek Dasmohapatra Feb. 9, 2021, 5:18 p.m. UTC
  If a DSO already exists (with the same name) in the base namespace
and it is flagged DT_GNU_UNIQUE then we should behave as if a proxy
had been requested.
---
 elf/dl-open.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
  

Comments

Adhemerval Zanella Feb. 19, 2021, 5:26 p.m. UTC | #1
On 09/02/2021 14:18, Vivek Das Mohapatra via Libc-alpha wrote:
> If a DSO already exists (with the same name) in the base namespace
> and it is flagged DT_GNU_UNIQUE then we should behave as if a proxy
> had been requested.
> ---
>  elf/dl-open.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index 441b8b1330..38b3587d4a 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -484,6 +484,7 @@ dl_open_worker (void *a)
>    const char *file = args->file;
>    int mode = args->mode;
>    struct link_map *call_map = NULL;
> +  struct link_map *preloaded = NULL;
>    int want_proxy = mode & RTLD_SHARED;
>    Lmid_t proxy_ns = LM_ID_BASE;
>  
> @@ -532,6 +533,23 @@ dl_open_worker (void *a)
>       may not be true if this is a recursive call to dlopen.  */
>    _dl_debug_initialize (0, args->nsid);
>  
> +  /* Target Lmid is not the base and we haven't explicitly asked for a proxy:
> +     We need to check for a matching DSO in the base Lmid in case it is flagged
> +     DT_GNU_FLAGS_1/DF_GNU_1_UNIQUE in which case we add RTLD_SHARED to the
> +     mode and set want_proxy.
> +     NOTE: RTLD_ISOLATE in the mode suppresses this behaviour.  */
> +  if (__glibc_unlikely (args->nsid != LM_ID_BASE) &&
> +      __glibc_likely (!want_proxy))

'want_proxy' is an int, check against '0'.

> +    {
> +      preloaded = _dl_find_dso (file, LM_ID_BASE);
> +
> +      if (preloaded && (preloaded->l_gnu_flags_1 & DF_GNU_1_UNIQUE))

No implicit checks.

> +        {
> +          want_proxy = RTLD_SHARED;
> +          mode |= RTLD_SHARED;
> +        }
> +    }
> +
>    /* Load the named object.  */
>    struct link_map *new;
>    args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,
>
  

Patch

diff --git a/elf/dl-open.c b/elf/dl-open.c
index 441b8b1330..38b3587d4a 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -484,6 +484,7 @@  dl_open_worker (void *a)
   const char *file = args->file;
   int mode = args->mode;
   struct link_map *call_map = NULL;
+  struct link_map *preloaded = NULL;
   int want_proxy = mode & RTLD_SHARED;
   Lmid_t proxy_ns = LM_ID_BASE;
 
@@ -532,6 +533,23 @@  dl_open_worker (void *a)
      may not be true if this is a recursive call to dlopen.  */
   _dl_debug_initialize (0, args->nsid);
 
+  /* Target Lmid is not the base and we haven't explicitly asked for a proxy:
+     We need to check for a matching DSO in the base Lmid in case it is flagged
+     DT_GNU_FLAGS_1/DF_GNU_1_UNIQUE in which case we add RTLD_SHARED to the
+     mode and set want_proxy.
+     NOTE: RTLD_ISOLATE in the mode suppresses this behaviour.  */
+  if (__glibc_unlikely (args->nsid != LM_ID_BASE) &&
+      __glibc_likely (!want_proxy))
+    {
+      preloaded = _dl_find_dso (file, LM_ID_BASE);
+
+      if (preloaded && (preloaded->l_gnu_flags_1 & DF_GNU_1_UNIQUE))
+        {
+          want_proxy = RTLD_SHARED;
+          mode |= RTLD_SHARED;
+        }
+    }
+
   /* Load the named object.  */
   struct link_map *new;
   args->map = new = _dl_map_object (call_map, file, lt_loaded, 0,