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