summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/sgs/include/rtld.h10
-rw-r--r--usr/src/cmd/sgs/libconv/common/group.c6
-rw-r--r--usr/src/cmd/sgs/libconv/common/group.msg3
-rw-r--r--usr/src/cmd/sgs/packages/common/SUNWonld-README1
-rw-r--r--usr/src/cmd/sgs/rtld/common/analyze.c44
-rw-r--r--usr/src/cmd/sgs/rtld/common/dlfcns.c35
-rw-r--r--usr/src/cmd/sgs/rtld/common/elf.c2
-rw-r--r--usr/src/cmd/sgs/rtld/common/remove.c29
-rw-r--r--usr/src/cmd/sgs/rtld/common/util.c35
-rw-r--r--usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c3
-rw-r--r--usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg3
11 files changed, 126 insertions, 45 deletions
diff --git a/usr/src/cmd/sgs/include/rtld.h b/usr/src/cmd/sgs/include/rtld.h
index c200ac0644..92147e26ce 100644
--- a/usr/src/cmd/sgs/include/rtld.h
+++ b/usr/src/cmd/sgs/include/rtld.h
@@ -418,11 +418,13 @@ typedef struct {
uint_t gd_flags; /* dependency flags */
} Grp_desc;
-#define GPD_AVAIL 0x0001 /* dependency available to dlsym() */
-#define GPD_ADDEPS 0x0002 /* dependencies of this dependency */
+#define GPD_DLSYM 0x0001 /* dependency available to dlsym() */
+#define GPD_RELOC 0x0002 /* dependency available to satisfy */
+ /* relocation binding */
+#define GPD_ADDEPS 0x0004 /* dependencies of this dependency */
/* should be added to handle */
-#define GPD_PARENT 0x0004 /* dependency is a parent */
-#define GPD_FILTER 0x0008 /* dependency is our filter */
+#define GPD_PARENT 0x0008 /* dependency is a parent */
+#define GPD_FILTER 0x0010 /* dependency is our filter */
#define GPD_REMOVE 0x1000 /* descriptor is a candidate for */
/* removal from the group */
diff --git a/usr/src/cmd/sgs/libconv/common/group.c b/usr/src/cmd/sgs/libconv/common/group.c
index f017558d64..fdf6b27ed6 100644
--- a/usr/src/cmd/sgs/libconv/common/group.c
+++ b/usr/src/cmd/sgs/libconv/common/group.c
@@ -67,7 +67,8 @@ conv_grphdl_flags(uint_t flags)
}
#define DESCSZ CONV_EXPN_FIELD_DEF_PREFIX_SIZE + \
- MSG_GPD_AVAIL_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
+ MSG_GPD_DLSYM_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
+ MSG_GPD_RELOC_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
MSG_GPD_ADDEPS_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
MSG_GPD_PARENT_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
MSG_GPD_FILTER_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
@@ -81,7 +82,8 @@ conv_grpdesc_flags(uint_t flags)
{
static char string[DESCSZ];
static Val_desc vda[] = {
- { GPD_AVAIL, MSG_ORIG(MSG_GPD_AVAIL) },
+ { GPD_DLSYM, MSG_ORIG(MSG_GPD_DLSYM) },
+ { GPD_RELOC, MSG_ORIG(MSG_GPD_RELOC) },
{ GPD_ADDEPS, MSG_ORIG(MSG_GPD_ADDEPS) },
{ GPD_PARENT, MSG_ORIG(MSG_GPD_PARENT) },
{ GPD_FILTER, MSG_ORIG(MSG_GPD_FILTER) },
diff --git a/usr/src/cmd/sgs/libconv/common/group.msg b/usr/src/cmd/sgs/libconv/common/group.msg
index fbaa47fa9d..1aa1c10e9c 100644
--- a/usr/src/cmd/sgs/libconv/common/group.msg
+++ b/usr/src/cmd/sgs/libconv/common/group.msg
@@ -32,7 +32,8 @@
@ MSG_GPH_FILTEE "GPH_FILTEE"
@ MSG_GPH_INITIAL "GPH_INITIAL"
-@ MSG_GPD_AVAIL "GPD_AVAIL"
+@ MSG_GPD_DLSYM "GPD_DLSYM"
+@ MSG_GPD_RELOC "GPD_RELOC"
@ MSG_GPD_ADDEPS "GPD_ADDEPS"
@ MSG_GPD_PARENT "GPD_PARENT"
@ MSG_GPD_FILTER "GPD_FILTER"
diff --git a/usr/src/cmd/sgs/packages/common/SUNWonld-README b/usr/src/cmd/sgs/packages/common/SUNWonld-README
index b5ba497852..e565c4764c 100644
--- a/usr/src/cmd/sgs/packages/common/SUNWonld-README
+++ b/usr/src/cmd/sgs/packages/common/SUNWonld-README
@@ -1249,3 +1249,4 @@ Bugid Risk Synopsis
6568745 segfault when using LD_DEBUG with bit_audit library when instrumenting
mozilla (D)
PSARC/2007/413 Add -zglobalaudit option to ld
+6573641 ld.so.1 does not maintain parent relationship to a dlopen() caller.
diff --git a/usr/src/cmd/sgs/rtld/common/analyze.c b/usr/src/cmd/sgs/rtld/common/analyze.c
index bf5561e6f6..f644848c18 100644
--- a/usr/src/cmd/sgs/rtld/common/analyze.c
+++ b/usr/src/cmd/sgs/rtld/common/analyze.c
@@ -2085,7 +2085,7 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
continue;
if ((exist = hdl_add(ghp, nlmp,
- (GPD_AVAIL | GPD_ADDEPS))) == 0)
+ (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS))) == 0)
return (0);
/*
@@ -2141,7 +2141,7 @@ load_finish(Lm_list *lml, const char *name, Rt_map *clmp, int nmode,
continue;
if ((exist = hdl_add(ghp, dlmp1,
- (GPD_AVAIL | GPD_ADDEPS))) != 0) {
+ (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS))) != 0) {
if (exist == ALE_CREATE) {
(void) update_mode(dlmp1, MODE(dlmp1),
nmode);
@@ -2512,21 +2512,47 @@ lookup_sym_direct(Slookup *slp, Rt_map **dlmp, uint_t *binfo, Syminfo *sip,
}
/*
- * If we need to direct bind to our parent start looking in each caller
- * link map.
+ * If we need to directly bind to our parent, start looking in each
+ * callers link map.
*/
sl = *slp;
sl.sl_flags |= LKUP_DIRECT;
sym = 0;
if (sip->si_boundto == SYMINFO_BT_PARENT) {
- Aliste off;
- Bnd_desc ** bdpp;
+ Aliste off1;
+ Bnd_desc **bdpp;
+ Grp_hdl **ghpp;
- for (ALIST_TRAVERSE(CALLERS(clmp), off, bdpp)) {
+ /*
+ * Determine the parent of this explicit dependency from its
+ * CALLERS()'s list.
+ */
+ for (ALIST_TRAVERSE(CALLERS(clmp), off1, bdpp)) {
sl.sl_imap = lmp = (*bdpp)->b_caller;
if ((sym = SYMINTP(lmp)(&sl, dlmp, binfo)) != 0)
- break;
+ goto found;
+ }
+
+ /*
+ * A caller can also be defined as the parent of a dlopen()
+ * call. Determine whether this object has any handles. The
+ * dependencies maintained with the handle represent the
+ * explicit dependencies of the dlopen()'ed object, and the
+ * calling parent.
+ */
+ for (ALIST_TRAVERSE(HANDLES(clmp), off1, ghpp)) {
+ Grp_hdl *ghp = *ghpp;
+ Grp_desc *gdp;
+ Aliste off2;
+
+ for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) {
+ if ((gdp->gd_flags & GPD_PARENT) == 0)
+ continue;
+ sl.sl_imap = lmp = gdp->gd_depend;
+ if ((sym = SYMINTP(lmp)(&sl, dlmp, binfo)) != 0)
+ goto found;
+ }
}
} else {
/*
@@ -2541,7 +2567,7 @@ lookup_sym_direct(Slookup *slp, Rt_map **dlmp, uint_t *binfo, Syminfo *sip,
if (lmp)
sym = SYMINTP(lmp)(&sl, dlmp, binfo);
}
-
+found:
if (sym)
*binfo |= DBG_BINFO_DIRECT;
diff --git a/usr/src/cmd/sgs/rtld/common/dlfcns.c b/usr/src/cmd/sgs/rtld/common/dlfcns.c
index 80af1b5a0d..a323e0bdbe 100644
--- a/usr/src/cmd/sgs/rtld/common/dlfcns.c
+++ b/usr/src/cmd/sgs/rtld/common/dlfcns.c
@@ -277,7 +277,7 @@ hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t flags)
ghp->gh_ownlmp = lml->lm_head;
ghp->gh_ownlml = lml;
} else {
- uint_t hflags = GPD_AVAIL;
+ uint_t hflags = (GPD_DLSYM | GPD_RELOC);
ghp->gh_ownlmp = nlmp;
ghp->gh_ownlml = LIST(nlmp);
@@ -286,7 +286,7 @@ hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t flags)
* As an optimization, a handle for ld.so.1 itself
* (required for libdl's filtering mechanism) shouldn't
* search any dependencies of ld.so.1. Omitting
- * GDP_ADDEPS prevents the addition of any ld.so.1
+ * GPD_ADDEPS prevents the addition of any ld.so.1
* dependencies to this handle.
*/
if ((flags & GPH_LDSO) == 0)
@@ -331,14 +331,24 @@ hdl_create(Lm_list *lml, Rt_map *nlmp, Rt_map *clmp, uint_t flags)
}
/*
- * If dlopen(..., RTLD_PARENT) add the caller to dependency list so that
- * it becomes part of this group. As we could be opened by different
- * parents this test is carried out every time a handle is requested.
- * Note that a parent doesn't provide symbols via dlsym() so it also
- * isn't necessary to add its dependencies to the handle.
+ * Keep track of the parent (caller). If this request stems from a
+ * dlopen(..., RTLD_PARENT) call, then the parent is made available to
+ * satisfy relocation bindings. Note, that individual, explicit,
+ * direct bindings can also be made to the parent should this object
+ * have been built defining PARENT symbol references. Also note that a
+ * parent doesn't provide symbols to dlsym() requests, so it isn't
+ * necessary to add the parents dependencies to the handle.
+ *
+ * As this object could be opened by different parents, this test is
+ * carried out every time a handle is requested.
*/
- if ((flags & GPH_PARENT) && clmp) {
- if (hdl_add(ghp, clmp, GPD_PARENT) == 0)
+ if (clmp) {
+ if (flags & GPH_PARENT)
+ flags = (GPD_PARENT | GPD_RELOC);
+ else
+ flags = GPD_PARENT;
+
+ if (hdl_add(ghp, clmp, flags) == 0)
return (0);
}
return (ghp);
@@ -393,7 +403,8 @@ hdl_initialize(Grp_hdl *ghp, Rt_map *nlmp, int mode, int promote)
if ((bdp->b_flags & BND_NEEDED) == 0)
continue;
- if (hdl_add(ghp, dlmp, (GPD_AVAIL | GPD_ADDEPS)) == 0)
+ if (hdl_add(ghp, dlmp,
+ (GPD_DLSYM | GPD_RELOC | GPD_ADDEPS)) == 0)
return (0);
(void) update_mode(dlmp, MODE(dlmp), mode);
@@ -1043,7 +1054,7 @@ dlsym_handle(Grp_hdl * ghp, Slookup * slp, Rt_map ** _lmp, uint_t *binfo)
Aliste off;
for (ALIST_TRAVERSE(ghp->gh_depends, off, gdp)) {
- if ((gdp->gd_flags & GPD_AVAIL) == 0)
+ if ((gdp->gd_flags & GPD_DLSYM) == 0)
continue;
sl.sl_imap = gdp->gd_depend;
@@ -1068,7 +1079,7 @@ dlsym_handle(Grp_hdl * ghp, Slookup * slp, Rt_map ** _lmp, uint_t *binfo)
for (ALIST_TRAVERSE(ghp->gh_depends, off, gdp)) {
nlmp = gdp->gd_depend;
- if (((gdp->gd_flags & GPD_AVAIL) == 0) ||
+ if (((gdp->gd_flags & GPD_DLSYM) == 0) ||
(LAZY(nlmp) == 0))
continue;
diff --git a/usr/src/cmd/sgs/rtld/common/elf.c b/usr/src/cmd/sgs/rtld/common/elf.c
index cef65a8aa2..cdae09ad62 100644
--- a/usr/src/cmd/sgs/rtld/common/elf.c
+++ b/usr/src/cmd/sgs/rtld/common/elf.c
@@ -1646,7 +1646,7 @@ _elf_lookup_filtee(Slookup *slp, Rt_map **dlmp, uint_t *binfo, uint_t ndx)
* Look for the symbol in the handles dependencies.
*/
for (ALIST_TRAVERSE(ghp->gh_depends, off, gdp)) {
- if ((gdp->gd_flags & GPD_AVAIL) == 0)
+ if ((gdp->gd_flags & GPD_DLSYM) == 0)
continue;
/*
diff --git a/usr/src/cmd/sgs/rtld/common/remove.c b/usr/src/cmd/sgs/rtld/common/remove.c
index eb7e8a0548..b56b5d7825 100644
--- a/usr/src/cmd/sgs/rtld/common/remove.c
+++ b/usr/src/cmd/sgs/rtld/common/remove.c
@@ -628,7 +628,8 @@ gdp_collect(Alist **ghalpp, Alist **lmalpp, Grp_hdl *ghp1)
* to analyze the parent itself for additional filters or
* deletion.
*/
- if ((gdp->gd_flags & GPD_ADDEPS) == 0)
+ if ((gdp->gd_flags & GPD_PARENT) ||
+ ((gdp->gd_flags & GPD_ADDEPS) == 0))
continue;
if ((action = alist_test(lmalpp, lmp, sizeof (Rt_map *),
@@ -1249,7 +1250,15 @@ remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
lmp = gdp->gd_depend;
- if (FLAGS(lmp) & FLG_RT_DELETE) {
+ /*
+ * Note, we must never delete a parent. The parent
+ * may already be tagged for deletion from a previous
+ * dlclose(). That dlclose has triggered this dlclose(),
+ * but the parents deletion is the responsibility of the
+ * previous dlclose(), not this one.
+ */
+ if ((FLAGS(lmp) & FLG_RT_DELETE) &&
+ ((gdp->gd_flags & GPD_PARENT) == 0)) {
flag = DBG_DEP_DELETE;
/*
@@ -1382,7 +1391,9 @@ remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
* sure the filtees reference count
* gets decremented.
*/
- if (FLAGS(lmp) & FLG_RT_DELETE) {
+ if ((FLAGS(lmp) & FLG_RT_DELETE) &&
+ ((gdp->gd_flags &
+ GPD_PARENT) == 0)) {
(void) dlclose_core(ghp,
lmp, lml);
}
@@ -1420,10 +1431,15 @@ remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
}
/*
- * Traverse each handle dependency.
+ * Traverse each handle dependency. Retain the dependencies
+ * flags to insure we don't delete any parents (the flags
+ * information is deleted as part of the alist removal that
+ * occurs before we inspect the object for deletion).
*/
for (ALIST_TRAVERSE(ghp->gh_depends, off2, gdp)) {
- if ((gdp->gd_flags & GPD_REMOVE) == 0)
+ uint_t flags = gdp->gd_flags;
+
+ if ((flags & GPD_REMOVE) == 0)
continue;
lmp = gdp->gd_depend;
@@ -1444,7 +1460,8 @@ remove_hdl(Grp_hdl *ghp, Rt_map *clmp, int *removed)
/*
* Complete the link-map deletion if appropriate.
*/
- if (FLAGS(lmp) & FLG_RT_DELETE) {
+ if ((FLAGS(lmp) & FLG_RT_DELETE) &&
+ ((flags & GPD_PARENT) == 0)) {
tls_modaddrem(lmp, TM_FLG_MODREM);
remove_so(LIST(lmp), lmp);
}
diff --git a/usr/src/cmd/sgs/rtld/common/util.c b/usr/src/cmd/sgs/rtld/common/util.c
index 9f58c87762..7a85048da8 100644
--- a/usr/src/cmd/sgs/rtld/common/util.c
+++ b/usr/src/cmd/sgs/rtld/common/util.c
@@ -3304,11 +3304,11 @@ leave(Lm_list *lml)
}
int
-callable(Rt_map * clmp, Rt_map * dlmp, Grp_hdl * ghp)
+callable(Rt_map *clmp, Rt_map *dlmp, Grp_hdl *ghp)
{
- Alist * calp, * dalp;
- Aliste cnt1, cnt2;
- Grp_hdl ** ghpp1, ** ghpp2;
+ Alist *calp, *dalp;
+ Aliste off1, off2;
+ Grp_hdl **ghpp1, **ghpp2;
/*
* An object can always find symbols within itself.
@@ -3342,7 +3342,7 @@ callable(Rt_map * clmp, Rt_map * dlmp, Grp_hdl * ghp)
/*
* Traverse the list of groups the caller is a part of.
*/
- for (ALIST_TRAVERSE(calp, cnt1, ghpp1)) {
+ for (ALIST_TRAVERSE(calp, off1, ghpp1)) {
/*
* If we're testing for the ability of two objects to bind to
* each other regardless of a specific group, ignore that group.
@@ -3353,9 +3353,28 @@ callable(Rt_map * clmp, Rt_map * dlmp, Grp_hdl * ghp)
/*
* Traverse the list of groups the destination is a part of.
*/
- for (ALIST_TRAVERSE(dalp, cnt2, ghpp2)) {
- if (*ghpp1 == *ghpp2)
- return (1);
+ for (ALIST_TRAVERSE(dalp, off2, ghpp2)) {
+ Grp_desc *gdp;
+ Aliste off3;
+
+ if (*ghpp1 != *ghpp2)
+ continue;
+
+ /*
+ * Make sure the relationship between the destination
+ * and the caller provide symbols for relocation.
+ * Parents are maintained as callers, but unless the
+ * destination object was opened with RTLD_PARENT, the
+ * parent doesn't provide symbols for the destination
+ * to relocate against.
+ */
+ for (ALIST_TRAVERSE((*ghpp2)->gh_depends, off3, gdp)) {
+ if (dlmp != gdp->gd_depend)
+ continue;
+
+ if (gdp->gd_flags & GPD_RELOC)
+ return (1);
+ }
}
}
return (0);
diff --git a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c
index 2a0b4ade77..796deaef8c 100644
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c
@@ -158,7 +158,8 @@ static const mdb_bitmask_t grhflags_bits[] = {
};
static const mdb_bitmask_t grdflags_bits[] = {
- { MSG_ORIG(MSG_GPD_AVAIL), GPD_AVAIL, GPD_AVAIL },
+ { MSG_ORIG(MSG_GPD_DLSYM), GPD_DLSYM, GPD_DLSYM },
+ { MSG_ORIG(MSG_GPD_RELOC), GPD_RELOC, GPD_RELOC },
{ MSG_ORIG(MSG_GPD_ADDEPS), GPD_ADDEPS, GPD_ADDEPS },
{ MSG_ORIG(MSG_GPD_PARENT), GPD_PARENT, GPD_PARENT },
{ MSG_ORIG(MSG_GPD_FILTER), GPD_FILTER, GPD_FILTER },
diff --git a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg
index 3e1ddc2a75..54467af25f 100644
--- a/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg
+++ b/usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg
@@ -139,7 +139,8 @@
@ MSG_GPH_INITIAL "INITIALIZED"
@ MSG_GPH_NOPENDLAZY "NO-PENDING-LAZY-DEPENDENCIES"
-@ MSG_GPD_AVAIL "AVAIL-TO-DLSYM"
+@ MSG_GPD_DLSYM "AVAIL-TO-DLSYM"
+@ MSG_GPD_RELOC "AVAIL-FOR-RELOCATION"
@ MSG_GPD_ADDEPS "ADD-DEPENDENCIES"
@ MSG_GPD_PARENT "PARENT"
@ MSG_GPD_FILTER "FILTER"