diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/sgs/include/rtld.h | 10 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libconv/common/group.c | 6 | ||||
-rw-r--r-- | usr/src/cmd/sgs/libconv/common/group.msg | 3 | ||||
-rw-r--r-- | usr/src/cmd/sgs/packages/common/SUNWonld-README | 1 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/common/analyze.c | 44 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/common/dlfcns.c | 35 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/common/elf.c | 2 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/common/remove.c | 29 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/common/util.c | 35 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/mdbmod/common/rtld.c | 3 | ||||
-rw-r--r-- | usr/src/cmd/sgs/rtld/mdbmod/common/rtld.msg | 3 |
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" |