@@ -950,7 +950,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
for (l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL; l = l->l_next)
if (!l->l_removed && _dl_file_id_match_p (&l->l_file_id, &id))
{
- if (!(l->l_flags_1 & DF_1_UNIQUE))
+ if (l->l_info[VALIDX (DT_GNU_UNIQUE)] == NULL)
continue;
/* Already loaded. Bump its reference count and return it. */
@@ -476,6 +476,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;
@@ -519,6 +520,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_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_info[VALIDX (DT_GNU_UNIQUE)] != NULL))
+ {
+ 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,
@@ -548,7 +566,7 @@ dl_open_worker (void *a)
return;
}
- /* If we were trying to load a DF_1_UNIQUE flagged DSO which was NOT
+ /* If we were trying to load a DT_GNU_UNIQUE flagged DSO which was NOT
ALREADY LOADED (or not loaded with the name we are using) then
_dl_map_object will return an instance from the main namespace.
We need to detect this and set up the RTLD_SHARED flags. */