Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 /*
     28  *	Copyright (c) 1988 AT&T
     29  *	  All Rights Reserved
     30  */
     31 
     32 /*
     33  * PATH setup and search directory functions.
     34  */
     35 
     36 #include	<stdio.h>
     37 #include	<unistd.h>
     38 #include	<limits.h>
     39 #include	<fcntl.h>
     40 #include	<string.h>
     41 #include	<sys/systeminfo.h>
     42 #include	<debug.h>
     43 #include	<conv.h>
     44 #include	"_rtld.h"
     45 #include	"msg.h"
     46 
     47 /*
     48  * Default and secure dependency search path initialization.
     49  */
     50 void
     51 set_dirs(Alist **alpp, Spath_defn *sdp, uint_t flags)
     52 {
     53 	while (sdp->sd_name) {
     54 		Pdesc	*pdp;
     55 
     56 		if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc),
     57 		    AL_CNT_SPATH)) == NULL)
     58 			return;
     59 
     60 		pdp->pd_pname = (char *)sdp->sd_name;
     61 		pdp->pd_plen = sdp->sd_len;
     62 		pdp->pd_flags = flags;
     63 		sdp++;
     64 	}
     65 }
     66 
     67 static void
     68 print_default_dirs(Lm_list *lml, Alist *alp, int search)
     69 {
     70 	uint_t	flags = 0;
     71 	int	num = 0;
     72 	Aliste	idx;
     73 	Pdesc	*pdp;
     74 
     75 	if (search)
     76 		(void) printf(MSG_INTL(MSG_LDD_PTH_BGNDFL));
     77 
     78 	for (ALIST_TRAVERSE(alp, idx, pdp)) {
     79 		flags = pdp->pd_flags;
     80 
     81 		if (search) {
     82 			const char	*fmt;
     83 
     84 			if (num++)
     85 				fmt = MSG_ORIG(MSG_LDD_FMT_PATHN);
     86 			else
     87 				fmt = MSG_ORIG(MSG_LDD_FMT_PATH1);
     88 
     89 			(void) printf(fmt, pdp->pd_pname);
     90 		} else
     91 			DBG_CALL(Dbg_libs_path(lml, pdp->pd_pname,
     92 			    pdp->pd_flags, config->c_name));
     93 	}
     94 
     95 	if (search) {
     96 		if (flags & LA_SER_CONFIG)
     97 			(void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFLC),
     98 			    config->c_name);
     99 		else
    100 			(void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFL));
    101 	}
    102 }
    103 
    104 /*
    105  * Given a search rule type, return a list of directories to search according
    106  * to the specified rule.
    107  */
    108 static Alist **
    109 get_dir_list(uchar_t rules, Rt_map *lmp, uint_t flags)
    110 {
    111 	Alist	**dalpp = NULL;
    112 	Lm_list *lml = LIST(lmp);
    113 	int	search;
    114 
    115 	/*
    116 	 * Determine whether ldd -s is in effect - ignore when we're searching
    117 	 * for audit libraries as these will be added to their own link-map.
    118 	 */
    119 	if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
    120 	    ((FLAGS1(lmp) & FL1_RT_LDDSTUB) == 0) &&
    121 	    ((flags & FLG_RT_AUDIT) == 0))
    122 		search = 1;
    123 	else
    124 		search = 0;
    125 
    126 	switch (rules) {
    127 	case RPLENV:
    128 		/*
    129 		 * Initialize the replaceable environment variable
    130 		 * (LD_LIBRARY_PATH) search path list.  Note, we always call
    131 		 * Dbg_libs_path() so that every library lookup diagnostic can
    132 		 * be preceded with the appropriate search path information.
    133 		 */
    134 		if (rpl_libpath) {
    135 			uint_t	mode = (LA_SER_LIBPATH | PD_FLG_UNIQUE);
    136 
    137 			/*
    138 			 * Note, this path may have originated from the users
    139 			 * environment or from a configuration file.
    140 			 */
    141 			if (env_info & ENV_INF_PATHCFG)
    142 				mode |= LA_SER_CONFIG;
    143 
    144 			DBG_CALL(Dbg_libs_path(lml, rpl_libpath, mode,
    145 			    config->c_name));
    146 
    147 			/*
    148 			 * For ldd(1) -s, indicate the search paths that'll
    149 			 * be used.  If this is a secure application then some
    150 			 * search paths may be ignored, therefore reset the
    151 			 * rpl_libdirs pointer each time so that the
    152 			 * diagnostics related to these unsecure directories
    153 			 * will be output for each image loaded.
    154 			 */
    155 			if (search) {
    156 				const char	*fmt;
    157 
    158 				if (env_info & ENV_INF_PATHCFG)
    159 					fmt = MSG_INTL(MSG_LDD_PTH_LIBPATHC);
    160 				else
    161 					fmt = MSG_INTL(MSG_LDD_PTH_LIBPATH);
    162 
    163 				(void) printf(fmt, rpl_libpath, config->c_name);
    164 			}
    165 			if (rpl_libdirs && (rtld_flags & RT_FL_SECURE) &&
    166 			    (search || DBG_ENABLED))
    167 				remove_plist(&rpl_libdirs, 1);
    168 
    169 			if (rpl_libdirs == NULL) {
    170 				/*
    171 				 * If this is a secure application we need to
    172 				 * be selective over what directories we use.
    173 				 */
    174 				(void) expand_paths(lmp, rpl_libpath,
    175 				    &rpl_libdirs, AL_CNT_SEARCH, mode,
    176 				    PD_TKN_HWCAP);
    177 			}
    178 			dalpp = &rpl_libdirs;
    179 		}
    180 		break;
    181 	case PRMENV:
    182 		/*
    183 		 * Initialize the permanent (LD_LIBRARY_PATH) search path list.
    184 		 * This can only originate from a configuration file.  To be
    185 		 * consistent with the debugging display of DEFENV (above),
    186 		 * always call Dbg_libs_path().
    187 		 */
    188 		if (prm_libpath) {
    189 			uint_t	mode =
    190 			    (LA_SER_LIBPATH | LA_SER_CONFIG | PD_FLG_UNIQUE);
    191 
    192 			DBG_CALL(Dbg_libs_path(lml, prm_libpath, mode,
    193 			    config->c_name));
    194 
    195 			/*
    196 			 * For ldd(1) -s, indicate the search paths that'll
    197 			 * be used.  If this is a secure application then some
    198 			 * search paths may be ignored, therefore reset the
    199 			 * prm_libdirs pointer each time so that the
    200 			 * diagnostics related to these unsecure directories
    201 			 * will be output for each image loaded.
    202 			 */
    203 			if (search)
    204 				(void) printf(MSG_INTL(MSG_LDD_PTH_LIBPATHC),
    205 				    prm_libpath, config->c_name);
    206 			if (prm_libdirs && (rtld_flags & RT_FL_SECURE) &&
    207 			    (search || DBG_ENABLED))
    208 				remove_plist(&prm_libdirs, 1);
    209 
    210 			if (prm_libdirs == NULL) {
    211 				/*
    212 				 * If this is a secure application we need to
    213 				 * be selective over what directories we use.
    214 				 */
    215 				(void) expand_paths(lmp, prm_libpath,
    216 				    &prm_libdirs, AL_CNT_SEARCH, mode,
    217 				    PD_TKN_HWCAP);
    218 			}
    219 			dalpp = &prm_libdirs;
    220 		}
    221 		break;
    222 	case RUNPATH:
    223 		/*
    224 		 * Initialize the runpath search path list.  To be consistent
    225 		 * with the debugging display of DEFENV (above), always call
    226 		 * Dbg_libs_path().
    227 		 */
    228 		if (RPATH(lmp)) {
    229 			DBG_CALL(Dbg_libs_path(lml, RPATH(lmp), LA_SER_RUNPATH,
    230 			    NAME(lmp)));
    231 
    232 			/*
    233 			 * For ldd(1) -s, indicate the search paths that'll
    234 			 * be used.  If this is a secure application then some
    235 			 * search paths may be ignored, therefore reset the
    236 			 * runlist pointer each time so that the diagnostics
    237 			 * related to these unsecure directories will be
    238 			 * output for each image loaded.
    239 			 */
    240 			if (search)
    241 				(void) printf(MSG_INTL(MSG_LDD_PTH_RUNPATH),
    242 				    RPATH(lmp), NAME(lmp));
    243 			if (RLIST(lmp) && (rtld_flags & RT_FL_SECURE) &&
    244 			    (search || DBG_ENABLED))
    245 				remove_plist(&RLIST(lmp), 1);
    246 
    247 			if (RLIST(lmp) == NULL) {
    248 				/*
    249 				 * If this is a secure application we need to
    250 				 * be selective over what directories we use.
    251 				 */
    252 				(void) expand_paths(lmp, RPATH(lmp),
    253 				    &RLIST(lmp), AL_CNT_SEARCH, LA_SER_RUNPATH,
    254 				    PD_TKN_HWCAP);
    255 			}
    256 			dalpp = &RLIST(lmp);
    257 		}
    258 		break;
    259 	case DEFAULT:
    260 		if ((FLAGS1(lmp) & FL1_RT_NODEFLIB) == 0) {
    261 			if ((rtld_flags & RT_FL_SECURE) &&
    262 			    (flags & (FLG_RT_PRELOAD | FLG_RT_AUDIT)))
    263 				dalpp = LM_SECURE_DIRS(lmp)();
    264 			else
    265 				dalpp = LM_DEFAULT_DIRS(lmp)();
    266 		}
    267 
    268 		/*
    269 		 * For ldd(1) -s, indicate the default paths that'll be used.
    270 		 */
    271 		if (dalpp && (search || DBG_ENABLED))
    272 			print_default_dirs(lml, *dalpp, search);
    273 		break;
    274 	default:
    275 		break;
    276 	}
    277 	return (dalpp);
    278 }
    279 
    280 /*
    281  * Get the next directory in the search rules path.  The seach path "cookie"
    282  * provided by the caller (sdp) maintains the state of a search in progress.
    283  *
    284  * Typically, a search consists of a series of rules that govern the order of
    285  * a search (ie. LD_LIBRARY_PATH, followed by RPATHS, followed by defaults).
    286  * Each rule can establish a corresponding series of path names, which are
    287  * maintained as an Alist.  The index within this Alist determines the present
    288  * search directory.
    289  */
    290 Pdesc *
    291 get_next_dir(Spath_desc *sdp, Rt_map *lmp, uint_t flags)
    292 {
    293 	/*
    294 	 * Make sure there are still rules to process.
    295 	 */
    296 	while (*sdp->sp_rule) {
    297 		Alist	*alp;
    298 
    299 		/*
    300 		 * If an Alist for this rule already exists, use if, otherwise
    301 		 * obtain an Alist for this rule.  Providing the Alist has
    302 		 * content, and the present Alist index is less than the number
    303 		 * of Alist members, return the associated path name descriptor.
    304 		 */
    305 		if ((sdp->sp_dalpp || ((sdp->sp_dalpp =
    306 		    get_dir_list(*sdp->sp_rule, lmp, flags)) != NULL)) &&
    307 		    ((alp = *sdp->sp_dalpp) != NULL) &&
    308 		    (alist_nitems(alp) > sdp->sp_idx)) {
    309 			return (alist_item(alp, sdp->sp_idx++));
    310 		}
    311 
    312 		/*
    313 		 * If no Alist for this rule exists, or if this is the last
    314 		 * element of this Alist, reset the Alist pointer and index,
    315 		 * and prepare for the next rule.
    316 		 */
    317 		sdp->sp_rule++;
    318 		sdp->sp_dalpp = NULL;
    319 		sdp->sp_idx = 0;
    320 	}
    321 
    322 	/*
    323 	 * All rules and search paths have been exhausted.
    324 	 */
    325 	return (NULL);
    326 }
    327 
    328 /*
    329  * Process a directory (runpath) or filename (needed or filter) string looking
    330  * for tokens to expand.  Allocate a new buffer for the string.
    331  */
    332 uint_t
    333 expand(char **name, size_t *len, char **list, uint_t orig, uint_t omit,
    334     Rt_map *lmp)
    335 {
    336 	char	_name[PATH_MAX];
    337 	char	*token = NULL, *oname, *ename, *optr, *_optr, *nptr, *_list;
    338 	size_t	olen = 0, nlen = 0, _len;
    339 	int	isaflag = 0;
    340 	uint_t	flags = 0;
    341 	Lm_list	*lml = LIST(lmp);
    342 
    343 	optr = _optr = oname = ename = *name;
    344 	ename += *len;
    345 	nptr = _name;
    346 
    347 	while ((olen < *len) && (nlen < PATH_MAX)) {
    348 		uint_t	_flags;
    349 
    350 		if ((*optr != '$') || ((olen - *len) == 1)) {
    351 			/*
    352 			 * When expanding paths while a configuration file
    353 			 * exists that contains directory information, determine
    354 			 * whether the path contains "./".  If so, we'll resolve
    355 			 * the path later to remove these relative entries.
    356 			 */
    357 			if ((rtld_flags & RT_FL_DIRCFG) &&
    358 			    (orig & LA_SER_MASK) && (*optr == '/') &&
    359 			    (optr != oname) && (*(optr - 1) == '.'))
    360 				flags |= TKN_DOTSLASH;
    361 
    362 			olen++, optr++;
    363 			continue;
    364 		}
    365 
    366 		/*
    367 		 * Copy any string we've presently passed over to the new
    368 		 * buffer.
    369 		 */
    370 		if ((_len = (optr - _optr)) != 0) {
    371 			if ((nlen += _len) < PATH_MAX) {
    372 				(void) strncpy(nptr, _optr, _len);
    373 				nptr = nptr + _len;
    374 			} else {
    375 				eprintf(lml, ERR_FATAL,
    376 				    MSG_INTL(MSG_ERR_EXPAND1), NAME(lmp),
    377 				    oname);
    378 				return (0);
    379 			}
    380 		}
    381 
    382 		/*
    383 		 * Skip the token delimiter and determine if a reserved token
    384 		 * match is found.
    385 		 */
    386 		olen++, optr++;
    387 		_flags = 0;
    388 		token = 0;
    389 
    390 		if (strncmp(optr, MSG_ORIG(MSG_TKN_ORIGIN),
    391 		    MSG_TKN_ORIGIN_SIZE) == 0) {
    392 			token = (char *)MSG_ORIG(MSG_TKN_ORIGIN);
    393 
    394 			/*
    395 			 * $ORIGIN expansion is required.  Determine this
    396 			 * objects basename.  Expansion of $ORIGIN is allowed
    397 			 * for secure applications but must be checked by the
    398 			 * caller to insure the expanded path matches a
    399 			 * registered secure name.
    400 			 */
    401 			if (((omit & PD_TKN_ORIGIN) == 0) &&
    402 			    (((_len = DIRSZ(lmp)) != 0) ||
    403 			    ((_len = fullpath(lmp, 0)) != 0))) {
    404 				if ((nlen += _len) < PATH_MAX) {
    405 					(void) strncpy(nptr,
    406 					    ORIGNAME(lmp), _len);
    407 					nptr = nptr +_len;
    408 					olen += MSG_TKN_ORIGIN_SIZE;
    409 					optr += MSG_TKN_ORIGIN_SIZE;
    410 					_flags |= PD_TKN_ORIGIN;
    411 				} else {
    412 					eprintf(lml, ERR_FATAL,
    413 					    MSG_INTL(MSG_ERR_EXPAND1),
    414 					    NAME(lmp), oname);
    415 					return (0);
    416 				}
    417 			}
    418 
    419 		} else if (strncmp(optr, MSG_ORIG(MSG_TKN_PLATFORM),
    420 		    MSG_TKN_PLATFORM_SIZE) == 0) {
    421 			token = (char *)MSG_ORIG(MSG_TKN_PLATFORM);
    422 
    423 			/*
    424 			 * $PLATFORM expansion required.  This would have been
    425 			 * established from the AT_SUN_PLATFORM aux vector, but
    426 			 * if not attempt to get it from sysconf().
    427 			 */
    428 			if (((omit & PD_TKN_PLATFORM) == 0) &&
    429 			    ((platform == 0) && (platform_sz == 0))) {
    430 				char	_info[SYS_NMLN];
    431 				long	_size;
    432 
    433 				_size = sysinfo(SI_PLATFORM, _info, SYS_NMLN);
    434 				if ((_size != -1) && ((platform =
    435 				    malloc((size_t)_size)) != NULL)) {
    436 					(void) strcpy(platform, _info);
    437 					platform_sz = (size_t)_size - 1;
    438 				}
    439 			}
    440 			if (((omit & PD_TKN_PLATFORM) == 0) &&
    441 			    (platform != 0)) {
    442 				if ((nlen += platform_sz) < PATH_MAX) {
    443 					(void) strncpy(nptr, platform,
    444 					    platform_sz);
    445 					nptr = nptr + platform_sz;
    446 					olen += MSG_TKN_PLATFORM_SIZE;
    447 					optr += MSG_TKN_PLATFORM_SIZE;
    448 					_flags |= PD_TKN_PLATFORM;
    449 				} else {
    450 					eprintf(lml, ERR_FATAL,
    451 					    MSG_INTL(MSG_ERR_EXPAND1),
    452 					    NAME(lmp), oname);
    453 					return (0);
    454 				}
    455 			}
    456 
    457 		} else if (strncmp(optr, MSG_ORIG(MSG_TKN_OSNAME),
    458 		    MSG_TKN_OSNAME_SIZE) == 0) {
    459 			token = (char *)MSG_ORIG(MSG_TKN_OSNAME);
    460 
    461 			/*
    462 			 * $OSNAME expansion required.  This is established
    463 			 * from the sysname[] returned by uname(2).
    464 			 */
    465 			if (((omit & PD_TKN_OSNAME) == 0) && (uts == NULL))
    466 				uts = conv_uts();
    467 
    468 			if (((omit & PD_TKN_OSNAME) == 0) &&
    469 			    (uts && uts->uts_osnamesz)) {
    470 				if ((nlen += uts->uts_osnamesz) < PATH_MAX) {
    471 					(void) strncpy(nptr, uts->uts_osname,
    472 					    uts->uts_osnamesz);
    473 					nptr = nptr + uts->uts_osnamesz;
    474 					olen += MSG_TKN_OSNAME_SIZE;
    475 					optr += MSG_TKN_OSNAME_SIZE;
    476 					_flags |= PD_TKN_OSNAME;
    477 				} else {
    478 					eprintf(lml, ERR_FATAL,
    479 					    MSG_INTL(MSG_ERR_EXPAND1),
    480 					    NAME(lmp), oname);
    481 					return (0);
    482 				}
    483 			}
    484 
    485 		} else if (strncmp(optr, MSG_ORIG(MSG_TKN_OSREL),
    486 		    MSG_TKN_OSREL_SIZE) == 0) {
    487 			token = (char *)MSG_ORIG(MSG_TKN_OSREL);
    488 
    489 			/*
    490 			 * $OSREL expansion required.  This is established
    491 			 * from the release[] returned by uname(2).
    492 			 */
    493 			if (((omit & PD_TKN_OSREL) == 0) && (uts == 0))
    494 				uts = conv_uts();
    495 
    496 			if (((omit & PD_TKN_OSREL) == 0) &&
    497 			    (uts && uts->uts_osrelsz)) {
    498 				if ((nlen += uts->uts_osrelsz) < PATH_MAX) {
    499 					(void) strncpy(nptr, uts->uts_osrel,
    500 					    uts->uts_osrelsz);
    501 					nptr = nptr + uts->uts_osrelsz;
    502 					olen += MSG_TKN_OSREL_SIZE;
    503 					optr += MSG_TKN_OSREL_SIZE;
    504 					_flags |= PD_TKN_OSREL;
    505 				} else {
    506 					eprintf(lml, ERR_FATAL,
    507 					    MSG_INTL(MSG_ERR_EXPAND1),
    508 					    NAME(lmp), oname);
    509 					return (0);
    510 				}
    511 			}
    512 
    513 		} else if ((strncmp(optr, MSG_ORIG(MSG_TKN_ISALIST),
    514 		    MSG_TKN_ISALIST_SIZE) == 0)) {
    515 			int	ok;
    516 			token = (char *)MSG_ORIG(MSG_TKN_ISALIST);
    517 
    518 			/*
    519 			 * $ISALIST expansion required.  When accompanied with
    520 			 * a list pointer, this routine updates that pointer
    521 			 * with the new list of potential candidates.  Without
    522 			 * this list pointer, only the first expansion is
    523 			 * provided.  NOTE, that two $ISLIST expansions within
    524 			 * the same path aren't supported.
    525 			 */
    526 			if ((omit & PD_TKN_ISALIST) || isaflag++)
    527 				ok = 0;
    528 			else
    529 				ok = 1;
    530 
    531 			if (ok && (isa == NULL))
    532 				isa = conv_isalist();
    533 
    534 			if (ok && isa && isa->isa_listsz) {
    535 				size_t	no, mlen, tlen, hlen = olen - 1;
    536 				char	*lptr;
    537 				Isa_opt *opt = isa->isa_opt;
    538 
    539 				if ((nlen += opt->isa_namesz) < PATH_MAX) {
    540 					(void) strncpy(nptr,  opt->isa_name,
    541 					    opt->isa_namesz);
    542 					nptr = nptr + opt->isa_namesz;
    543 					olen += MSG_TKN_ISALIST_SIZE;
    544 					optr += MSG_TKN_ISALIST_SIZE;
    545 					_flags |= PD_TKN_ISALIST;
    546 				} else {
    547 					eprintf(lml, ERR_FATAL,
    548 					    MSG_INTL(MSG_ERR_EXPAND1),
    549 					    NAME(lmp), oname);
    550 					return (0);
    551 				}
    552 
    553 				if (list) {
    554 					tlen = *len - olen;
    555 					mlen = ((hlen + tlen) *
    556 					    (isa->isa_optno - 1)) +
    557 					    isa->isa_listsz - opt->isa_namesz +
    558 					    strlen(*list);
    559 					if ((_list = lptr =
    560 					    malloc(mlen)) == NULL)
    561 						return (0);
    562 
    563 					for (no = 1, opt++; no < isa->isa_optno;
    564 					    no++, opt++) {
    565 						(void) strncpy(lptr, *name,
    566 						    hlen);
    567 						lptr = lptr + hlen;
    568 						(void) strncpy(lptr,
    569 						    opt->isa_name,
    570 						    opt->isa_namesz);
    571 						lptr = lptr + opt->isa_namesz;
    572 						(void) strncpy(lptr, optr,
    573 						    tlen);
    574 						lptr = lptr + tlen;
    575 						*lptr++ = ':';
    576 					}
    577 					if (**list)
    578 						(void) strcpy(lptr, *list);
    579 					else
    580 						*--lptr = '\0';
    581 				}
    582 			}
    583 
    584 		} else if (strncmp(optr, MSG_ORIG(MSG_TKN_HWCAP),
    585 		    MSG_TKN_HWCAP_SIZE) == 0) {
    586 			char	*bptr = nptr - 1;
    587 			char	*eptr = optr + MSG_TKN_HWCAP_SIZE;
    588 			token = (char *)MSG_ORIG(MSG_TKN_HWCAP);
    589 
    590 			/*
    591 			 * $HWCAP expansion required.  For compatibility with
    592 			 * older environments, only expand this token when hard-
    593 			 * ware capability information is available.   This
    594 			 * expansion is only allowed for non-simple path names
    595 			 * (must contain a '/'), with the token itself being the
    596 			 * last element of the path.  Therefore, all we need do
    597 			 * is test the existence of the string "/$HWCAP\0".
    598 			 */
    599 			if (((omit & PD_TKN_HWCAP) == 0) &&
    600 			    (rtld_flags2 & RT_FL2_HWCAP) &&
    601 			    ((bptr > _name) && (*bptr == '/') &&
    602 			    ((*eptr == '\0') || (*eptr == ':')))) {
    603 				/*
    604 				 * Decrement the present pointer so that the
    605 				 * directories trailing "/" gets nuked later.
    606 				 */
    607 				nptr--, nlen--;
    608 				olen += MSG_TKN_HWCAP_SIZE;
    609 				optr += MSG_TKN_HWCAP_SIZE;
    610 				_flags |= PD_TKN_HWCAP;
    611 			}
    612 
    613 		} else {
    614 			/*
    615 			 * If reserved token was not found, copy the
    616 			 * character.
    617 			 */
    618 			*nptr++ = '$';
    619 			nlen++;
    620 		}
    621 
    622 		/*
    623 		 * If a reserved token was found, and could not be expanded,
    624 		 * diagnose the error condition.
    625 		 */
    626 		if (token) {
    627 			if (_flags)
    628 				flags |= _flags;
    629 			else {
    630 				char	buf[PATH_MAX], *str;
    631 
    632 				/*
    633 				 * Note, the original string we're expanding
    634 				 * might contain a number of ':' separated
    635 				 * paths.  Isolate the path we're processing to
    636 				 * provide a more precise error diagnostic.
    637 				 */
    638 				if (str = strchr(oname, ':')) {
    639 					size_t	slen = str - oname;
    640 
    641 					(void) strncpy(buf, oname, slen);
    642 					buf[slen] = '\0';
    643 					str = buf;
    644 				} else
    645 					str = oname;
    646 
    647 				eprintf(lml, ERR_FATAL,
    648 				    MSG_INTL(MSG_ERR_EXPAND2), NAME(lmp),
    649 				    str, token);
    650 				return (0);
    651 			}
    652 		}
    653 		_optr = optr;
    654 	}
    655 
    656 	/*
    657 	 * First make sure the current length is shorter than PATH_MAX.  We may
    658 	 * arrive here if the given path contains '$' characters which are not
    659 	 * the lead of a reserved token.
    660 	 */
    661 	if (nlen >= PATH_MAX) {
    662 		eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_EXPAND1), NAME(lmp),
    663 		    oname);
    664 		return (0);
    665 	}
    666 
    667 	/*
    668 	 * If any ISALIST processing has occurred not only do we return the
    669 	 * expanded node we're presently working on, but we can also update the
    670 	 * remaining list so that it is effectively prepended with this node
    671 	 * expanded to all remaining ISALIST options.  Note that we can only
    672 	 * handle one ISALIST per node.  For more than one ISALIST to be
    673 	 * processed we'd need a better algorithm than above to replace the
    674 	 * newly generated list.  Whether we want to encourage the number of
    675 	 * path name permutations this would provide is another question.  So,
    676 	 * for now if more than one ISALIST is encountered we return the
    677 	 * original node untouched.
    678 	 */
    679 	if (isa && isaflag) {
    680 		if (isaflag == 1) {
    681 			if (list)
    682 				*list = _list;
    683 		} else {
    684 			flags &= ~PD_TKN_ISALIST;
    685 			if ((nptr = (char *)stravl_insert(*name, 0,
    686 			    (*len + 1), 1)) == NULL)
    687 				return (0);
    688 			*name = nptr;
    689 			return (TKN_NONE);
    690 		}
    691 	}
    692 
    693 	/*
    694 	 * Copy any remaining string. Terminate the new string with a null as
    695 	 * this string can be displayed via debugging diagnostics.
    696 	 */
    697 	if ((_len = (optr - _optr)) != 0) {
    698 		if ((nlen += _len) < PATH_MAX) {
    699 			(void) strncpy(nptr, _optr, _len);
    700 			nptr = nptr + _len;
    701 		} else {
    702 			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_EXPAND1),
    703 			    NAME(lmp), oname);
    704 			return (0);
    705 		}
    706 	}
    707 	*nptr = '\0';
    708 
    709 	/*
    710 	 * A path that has been expanded is typically used to create full
    711 	 * path names for objects that will be opened.  The final path name is
    712 	 * resolved to simplify it, and set the stage for possible $ORIGIN
    713 	 * processing.  Therefore, it's usually unnecessary to resolve the path
    714 	 * at this point.  However, if a configuration file, containing
    715 	 * directory information is in use, then we might need to lookup this
    716 	 * path in the configuration file.  To keep the number of path name
    717 	 * resolutions to a minimum, only resolve paths that contain "./".  The
    718 	 * use of "$ORIGIN/../lib" will probably only match a configuration file
    719 	 * entry after resolution.
    720 	 */
    721 	if (list && (rtld_flags & RT_FL_DIRCFG) && (flags & TKN_DOTSLASH)) {
    722 		int	len;
    723 
    724 		if ((len = resolvepath(_name, _name, (PATH_MAX - 1))) >= 0) {
    725 			nlen = (size_t)len;
    726 			_name[nlen] = '\0';
    727 			flags |= PD_TKN_RESOLVED;
    728 		}
    729 	}
    730 
    731 	/*
    732 	 * Allocate a new string if necessary.
    733 	 *
    734 	 * If any form of token expansion, or string resolution has occurred,
    735 	 * the storage must be allocated for the new string.
    736 	 *
    737 	 * If we're processing a substring, for example, any string besides the
    738 	 * last string within a search path "A:B:C", then this substring needs
    739 	 * to be isolated with a null terminator.  However, if this search path
    740 	 * was created from a previous ISALIST expansion, then all strings must
    741 	 * be allocated, as the isalist expansion will be freed after expansion
    742 	 * processing.
    743 	 */
    744 	if ((nptr = (char *)stravl_insert(_name, 0, (nlen + 1), 1)) == NULL)
    745 		return (0);
    746 	*name = nptr;
    747 	*len = nlen;
    748 	return (flags ? flags : TKN_NONE);
    749 }
    750 
    751 /*
    752  * Determine whether a path name is secure.
    753  */
    754 int
    755 is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags)
    756 {
    757 	Alist		**salpp;
    758 	Aliste		idx;
    759 	char		buffer[PATH_MAX], *npath = NULL;
    760 	Lm_list		*lml = LIST(clmp);
    761 	Pdesc		*pdp;
    762 
    763 	/*
    764 	 * If a path name originates from a configuration file, use it.  The use
    765 	 * of a configuration file is already validated for secure applications,
    766 	 * so if we're using a configuration file, we must be able to use all
    767 	 * that it defines.
    768 	 */
    769 	if (info & LA_SER_CONFIG)
    770 		return (1);
    771 
    772 	if ((info & LA_SER_MASK) == 0) {
    773 		char	*str;
    774 
    775 		/*
    776 		 * If the path name specifies a file (rather than a directory),
    777 		 * peel off the file before making the comparison.
    778 		 */
    779 		str = strrchr(opath, '/');
    780 
    781 		/*
    782 		 * Carry out some initial security checks.
    783 		 *
    784 		 *   .	a simple file name (one containing no "/") is fine, as
    785 		 *	this file name will be combined with search paths to
    786 		 *	determine the complete path.  Note, a secure application
    787 		 *	may provide a configuration file, and this can only be
    788 		 *	a full path name (PN_FLG_FULLPATH).
    789 		 *   .	a full path (one starting with "/") is fine, provided
    790 		 *	this path name isn't a preload/audit path.
    791 		 *   .	provided $ORIGIN expansion has not been employed, the
    792 		 *	above categories of path are deemed secure.
    793 		 */
    794 		if ((((str == 0) && ((info & PD_FLG_FULLPATH) == 0)) ||
    795 		    ((*opath == '/') && (str != opath) &&
    796 		    ((info & PD_FLG_EXTLOAD) == 0))) &&
    797 		    ((flags & PD_TKN_ORIGIN) == 0))
    798 			return (1);
    799 
    800 		/*
    801 		 * Determine the directory name of the present path.
    802 		 */
    803 		if (str) {
    804 			if (str == opath)
    805 				npath = (char *)MSG_ORIG(MSG_STR_SLASH);
    806 			else {
    807 				size_t	size;
    808 
    809 				if ((size = str - opath) >= PATH_MAX)
    810 					return (0);
    811 
    812 				(void) strncpy(buffer, opath, size);
    813 				buffer[size] = '\0';
    814 				npath = buffer;
    815 			}
    816 
    817 			/*
    818 			 * If $ORIGIN processing has been employed, then allow
    819 			 * any directory that has already been used to satisfy
    820 			 * other dependencies, to be used.
    821 			 */
    822 			if ((flags & PD_TKN_ORIGIN) &&
    823 			    spavl_recorded(npath, 0)) {
    824 				DBG_CALL(Dbg_libs_insecure(lml, npath, 1));
    825 				return (1);
    826 			}
    827 		}
    828 	} else {
    829 		/*
    830 		 * A search path, i.e., RPATH, configuration file path, etc. is
    831 		 * used as is.  Exceptions to this are:
    832 		 *
    833 		 *   .	LD_LIBRARY_PATH.
    834 		 *   .	any $ORIGIN expansion, unless used by a setuid ld.so.1
    835 		 *	to find its own dependencies, or the path name has
    836 		 *	already been used to find other dependencies.
    837 		 *   .	any relative path.
    838 		 */
    839 		if (((info & LA_SER_LIBPATH) == 0) && (*opath == '/') &&
    840 		    ((flags & PD_TKN_ORIGIN) == 0))
    841 			return (1);
    842 
    843 		/*
    844 		 * If $ORIGIN processing is requested, allow a setuid ld.so.1
    845 		 * to use this path for its own dependencies.  Allow the
    846 		 * application to use this path name only if the path name has
    847 		 * already been used to locate other dependencies.
    848 		 */
    849 		if (flags & PD_TKN_ORIGIN) {
    850 			if ((lml->lm_flags & LML_FLG_RTLDLM) &&
    851 			    is_rtld_setuid())
    852 				return (1);
    853 			else if (spavl_recorded(opath, 0)) {
    854 				DBG_CALL(Dbg_libs_insecure(lml, opath, 1));
    855 				return (1);
    856 			}
    857 		}
    858 		npath = (char *)opath;
    859 	}
    860 
    861 	/*
    862 	 * Determine whether the present directory is trusted.
    863 	 */
    864 	if (npath) {
    865 		salpp = LM_SECURE_DIRS(LIST(clmp)->lm_head)();
    866 		for (ALIST_TRAVERSE(*salpp, idx, pdp)) {
    867 			if (strcmp(npath, pdp->pd_pname) == 0)
    868 				return (1);
    869 		}
    870 	}
    871 
    872 	/*
    873 	 * The path is insecure, so depending on the caller, provide a
    874 	 * diagnostic.  Preloaded, or audit libraries generate a warning, as
    875 	 * the process will run without them.
    876 	 */
    877 	if (info & PD_FLG_EXTLOAD) {
    878 		if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
    879 			if ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)
    880 				(void) printf(MSG_INTL(MSG_LDD_FIL_ILLEGAL),
    881 				    opath);
    882 		} else
    883 			eprintf(lml, ERR_WARNING, MSG_INTL(MSG_SEC_ILLEGAL),
    884 			    opath);
    885 
    886 		return (0);
    887 	}
    888 
    889 	/*
    890 	 * Explicit file references are fatal.
    891 	 */
    892 	if ((info & LA_SER_MASK) == 0) {
    893 		if (lml->lm_flags & LML_FLG_TRC_ENABLE) {
    894 			/* BEGIN CSTYLED */
    895 			if ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0) {
    896 				if (lml->lm_flags &
    897 				    (LML_FLG_TRC_VERBOSE | LML_FLG_TRC_SEARCH))
    898 					(void) printf(
    899 					    MSG_INTL(MSG_LDD_FIL_FIND),
    900 					    opath, NAME(clmp));
    901 
    902 				if (((rtld_flags & RT_FL_SILENCERR) == 0) ||
    903 				    (lml->lm_flags & LML_FLG_TRC_VERBOSE))
    904 					(void) printf(
    905 					    MSG_INTL(MSG_LDD_FIL_ILLEGAL),
    906 					    opath);
    907 			}
    908 			/* END CSTYLED */
    909 		} else
    910 			eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), opath,
    911 			    strerror(EACCES));
    912 	} else {
    913 		/*
    914 		 * Search paths.
    915 		 */
    916 		DBG_CALL(Dbg_libs_insecure(lml, opath, 0));
    917 		if ((lml->lm_flags & LML_FLG_TRC_SEARCH) &&
    918 		    ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0))
    919 			(void) printf(MSG_INTL(MSG_LDD_PTH_IGNORE), opath);
    920 	}
    921 	return (0);
    922 }
    923 
    924 /*
    925  * Determine whether a path already exists within the callers Pnode list.
    926  */
    927 inline static uint_t
    928 is_path_unique(Alist *alp, const char *path)
    929 {
    930 	Aliste	idx;
    931 	Pdesc	*pdp;
    932 
    933 	for (ALIST_TRAVERSE(alp, idx, pdp)) {
    934 		if (pdp->pd_plen && (strcmp(pdp->pd_pname, path) == 0))
    935 			return (PD_FLG_DUPLICAT);
    936 	}
    937 	return (0);
    938 }
    939 
    940 /*
    941  * Expand one or more path names.  This routine is called for all path strings,
    942  * i.e., NEEDED, rpaths, default search paths, configuration file search paths,
    943  * filtees, etc.  The path may be a single path name, or a colon separated list
    944  * of path names.  Each individual path name is processed for possible reserved
    945  * token expansion.  All string nodes are maintained in allocated memory
    946  * (regardless of whether they are constant (":"), or token expanded) to
    947  * simplify path name descriptor removal.
    948  *
    949  * The info argument passes in auxiliary information regarding the callers
    950  * intended use of the path names.  This information may be maintained in the
    951  * path name descriptor element produced to describe the path name (i.e.,
    952  * LA_SER_LIBPATH etc.), or may be used to determine additional security or
    953  * diagnostic processing.
    954  */
    955 int
    956 expand_paths(Rt_map *clmp, const char *list, Alist **alpp, Aliste alni,
    957     uint_t orig, uint_t omit)
    958 {
    959 	char	*str, *olist = 0, *nlist = (char *)list;
    960 	int	fnull = FALSE;	/* TRUE if empty final path segment seen */
    961 	Pdesc	*pdp = NULL;
    962 
    963 	for (str = nlist; *nlist || fnull; str = nlist) {
    964 		char	*ostr;
    965 		char	*elist = NULL;
    966 		size_t	len, olen;
    967 		uint_t	tkns = 0;
    968 
    969 		if (*nlist == ';')
    970 			++nlist, ++str;
    971 		if ((*nlist == ':') || fnull) {
    972 			/* If not a final null segment, check following one */
    973 			fnull = !(fnull || *(nlist + 1));
    974 
    975 			if (*nlist)
    976 				nlist++;
    977 
    978 			/*
    979 			 * When the shell sees a null PATH segment, it
    980 			 * treats it as if it were the cwd (.). We mimic
    981 			 * this behavior for LD_LIBRARY_PATH and runpaths
    982 			 * (mainly for backwards compatibility with previous
    983 			 * behavior). For other paths, this makes no sense,
    984 			 * so we simply ignore the segment.
    985 			 */
    986 			if (!(orig & (LA_SER_LIBPATH | LA_SER_RUNPATH)))
    987 				continue; /* Process next segment */
    988 
    989 			str = (char *)MSG_ORIG(MSG_FMT_CWD);
    990 			len = MSG_FMT_CWD_SIZE;
    991 
    992 		} else {
    993 			uint_t	_tkns;
    994 
    995 			len = 0;
    996 			while (*nlist && (*nlist != ':') && (*nlist != ';')) {
    997 				if (*nlist == '/')
    998 					tkns |= PD_FLG_PNSLASH;
    999 				nlist++, len++;
   1000 			}
   1001 
   1002 			/* Check for a following final null segment */
   1003 			fnull = (*nlist == ':') && !*(nlist + 1);
   1004 
   1005 			if (*nlist)
   1006 				nlist++;
   1007 
   1008 			/*
   1009 			 * Expand the captured string.  Besides expanding the
   1010 			 * present path/file entry, we may have a new list to
   1011 			 * deal with (ISALIST expands to multiple new entries).
   1012 			 */
   1013 			elist = nlist;
   1014 			ostr = str;
   1015 			olen = len;
   1016 			if ((_tkns = expand(&str, &len, &elist, orig, omit,
   1017 			    clmp)) == 0)
   1018 				continue;
   1019 			tkns |= _tkns;
   1020 		}
   1021 
   1022 		/*
   1023 		 * If this a secure application, validation of the expanded
   1024 		 * path name may be necessary.
   1025 		 */
   1026 		if ((rtld_flags & RT_FL_SECURE) &&
   1027 		    (is_path_secure(str, clmp, orig, tkns) == 0))
   1028 			continue;
   1029 
   1030 		/*
   1031 		 * If required, ensure that the string is unique.  For search
   1032 		 * paths such as LD_LIBRARY_PATH, users often inherit multiple
   1033 		 * paths which result in unnecessary duplication.  Note, if
   1034 		 * we're debugging, any duplicate entry is retained and flagged
   1035 		 * so that the entry can be diagnosed later as part of unused
   1036 		 * processing.
   1037 		 */
   1038 		if (orig & PD_FLG_UNIQUE) {
   1039 			Word	tracing;
   1040 
   1041 			tracing = LIST(clmp)->lm_flags &
   1042 			    (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED);
   1043 			tkns |= is_path_unique(*alpp, str);
   1044 
   1045 			/*
   1046 			 * Note, use the debug strings rpl_debug and prm_debug
   1047 			 * as an indicator that debugging has been requested,
   1048 			 * rather than DBG_ENABLE(), as the initial use of
   1049 			 * LD_LIBRARY_PATH occurs in preparation for loading
   1050 			 * our debugging library.
   1051 			 */
   1052 			if ((tkns & PD_FLG_DUPLICAT) && (tracing == 0) &&
   1053 			    (rpl_debug == 0) && (prm_debug == 0))
   1054 				continue;
   1055 		}
   1056 
   1057 		/*
   1058 		 * Create a new pathname descriptor.
   1059 		 */
   1060 		if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc),
   1061 		    alni)) == NULL)
   1062 			return (0);
   1063 
   1064 		pdp->pd_pname = str;
   1065 		pdp->pd_plen = len;
   1066 		pdp->pd_flags = (orig & LA_SER_MASK) | (tkns & PD_MSK_INHERIT);
   1067 
   1068 		/*
   1069 		 * If token expansion occurred, maintain the original string.
   1070 		 * This string can be used to provide a more informative error
   1071 		 * diagnostic for a file that fails to load, or for displaying
   1072 		 * unused search paths.
   1073 		 */
   1074 		if ((tkns & PD_MSK_EXPAND) && ((pdp->pd_oname =
   1075 		    stravl_insert(ostr, 0, (olen + 1), 1)) == NULL))
   1076 			return (0);
   1077 
   1078 		/*
   1079 		 * Now that any duplication of the original string has occurred,
   1080 		 * release any previous old listing.
   1081 		 */
   1082 		if (elist && (elist != nlist)) {
   1083 			if (olist)
   1084 				free(olist);
   1085 			nlist = olist = elist;
   1086 		}
   1087 	}
   1088 
   1089 	if (olist)
   1090 		free(olist);
   1091 
   1092 	/*
   1093 	 * If no paths could be determined (perhaps because of security), then
   1094 	 * indicate a failure.
   1095 	 */
   1096 	return (pdp != NULL);
   1097 }
   1098 
   1099 /*
   1100  * Establish an objects fully resolved path.
   1101  *
   1102  * When $ORIGIN was first introduced, the expansion of a relative path name was
   1103  * deferred until it was required.  However now we insure a full path name is
   1104  * always created - things like the analyzer wish to rely on librtld_db
   1105  * returning a full path.  The overhead of this is perceived to be low,
   1106  * providing the associated libc version of getcwd is available (see 4336878).
   1107  * This getcwd() was ported back to Solaris 8.1.
   1108  */
   1109 size_t
   1110 fullpath(Rt_map *lmp, Fdesc *fdp)
   1111 {
   1112 	const char	*name;
   1113 
   1114 	/*
   1115 	 * Determine whether this path name is already resolved.
   1116 	 */
   1117 	if (fdp && (fdp->fd_flags & FLG_FD_RESOLVED)) {
   1118 		/*
   1119 		 * If the resolved path differed from the original name, the
   1120 		 * resolved path would have been recorded as the fd_pname.
   1121 		 * Steal this path name from the file descriptor.  Otherwise,
   1122 		 * the path name is the same as the name of this object.
   1123 		 */
   1124 		if (fdp->fd_pname)
   1125 			PATHNAME(lmp) = fdp->fd_pname;
   1126 		else
   1127 			PATHNAME(lmp) = NAME(lmp);
   1128 	} else {
   1129 		/*
   1130 		 * If this path name has not yet been resolved, resolve the
   1131 		 * current name.
   1132 		 */
   1133 		char		_path[PATH_MAX];
   1134 		const char	*path;
   1135 		int		size, rsize;
   1136 
   1137 		if (fdp && fdp->fd_pname)
   1138 			PATHNAME(lmp) = fdp->fd_pname;
   1139 		else
   1140 			PATHNAME(lmp) = NAME(lmp);
   1141 
   1142 		name = path = PATHNAME(lmp);
   1143 		size = strlen(name);
   1144 
   1145 		if (path[0] != '/') {
   1146 			/*
   1147 			 * If we can't determine the current directory (possible
   1148 			 * if too many files are open - EMFILE), or if the
   1149 			 * created path is too big, simply revert back to the
   1150 			 * initial path name.
   1151 			 */
   1152 			if (getcwd(_path, (PATH_MAX - 2 - size)) != NULL) {
   1153 				(void) strcat(_path, MSG_ORIG(MSG_STR_SLASH));
   1154 				(void) strcat(_path, name);
   1155 				path = _path;
   1156 				size = strlen(path);
   1157 			}
   1158 		}
   1159 
   1160 		/*
   1161 		 * See if the path name can be reduced further.
   1162 		 */
   1163 		if ((rsize = resolvepath(path, _path, (PATH_MAX - 1))) > 0) {
   1164 			_path[rsize] = '\0';
   1165 			path = _path;
   1166 			size = rsize;
   1167 		}
   1168 
   1169 		/*
   1170 		 * If the path name is different from the original, duplicate it
   1171 		 * so that it is available in a core file.  If the duplication
   1172 		 * fails simply leave the original path name alone.
   1173 		 */
   1174 		if ((PATHNAME(lmp) =
   1175 		    stravl_insert(path, 0, (size + 1), 0)) == NULL)
   1176 			PATHNAME(lmp) = name;
   1177 	}
   1178 
   1179 	name = ORIGNAME(lmp) = PATHNAME(lmp);
   1180 
   1181 	/*
   1182 	 * Establish the directory name size - this also acts as a flag that the
   1183 	 * directory name has been computed.
   1184 	 */
   1185 	DIRSZ(lmp) = strrchr(name, '/') - name;
   1186 	return (DIRSZ(lmp));
   1187 }
   1188