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.
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.
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]
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Copyright (c) 1988 AT&T
31 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
35 * PATH setup and search directory functions.
49 * Default and secure dependency search path initialization.
52 set_dirs(Alist
**alpp
, Spath_defn
*sdp
, uint_t flags
)
54 while (sdp
->sd_name
) {
57 if ((pdp
= alist_append(alpp
, NULL
, sizeof (Pdesc
),
58 AL_CNT_SPATH
)) == NULL
)
61 pdp
->pd_pname
= (char *)sdp
->sd_name
;
62 pdp
->pd_plen
= sdp
->sd_len
;
63 pdp
->pd_flags
= flags
;
69 print_default_dirs(Lm_list
*lml
, Alist
*alp
, int search
)
77 (void) printf(MSG_INTL(MSG_LDD_PTH_BGNDFL
));
79 for (ALIST_TRAVERSE(alp
, idx
, pdp
)) {
80 flags
= pdp
->pd_flags
;
86 fmt
= MSG_ORIG(MSG_LDD_FMT_PATHN
);
88 fmt
= MSG_ORIG(MSG_LDD_FMT_PATH1
);
90 (void) printf(fmt
, pdp
->pd_pname
);
92 DBG_CALL(Dbg_libs_path(lml
, pdp
->pd_pname
,
93 pdp
->pd_flags
, config
->c_name
));
97 if (flags
& LA_SER_CONFIG
)
98 (void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFLC
),
101 (void) printf(MSG_INTL(MSG_LDD_PTH_ENDDFL
));
106 * Given a search rule type, return a list of directories to search according
107 * to the specified rule.
110 get_dir_list(uchar_t rules
, Rt_map
*lmp
, uint_t flags
)
112 Alist
**dalpp
= NULL
;
113 Lm_list
*lml
= LIST(lmp
);
117 * Determine whether ldd -s is in effect - ignore when we're searching
118 * for audit libraries as these will be added to their own link-map.
120 if ((lml
->lm_flags
& LML_FLG_TRC_SEARCH
) &&
121 ((FLAGS1(lmp
) & FL1_RT_LDDSTUB
) == 0) &&
122 ((flags
& FLG_RT_AUDIT
) == 0))
130 * Initialize the replaceable environment variable
131 * (LD_LIBRARY_PATH) search path list. Note, we always call
132 * Dbg_libs_path() so that every library lookup diagnostic can
133 * be preceded with the appropriate search path information.
136 uint_t mode
= (LA_SER_LIBPATH
| PD_FLG_UNIQUE
);
139 * Note, this path may have originated from the users
140 * environment or from a configuration file.
142 if (env_info
& ENV_INF_PATHCFG
)
143 mode
|= LA_SER_CONFIG
;
145 DBG_CALL(Dbg_libs_path(lml
, rpl_libpath
, mode
,
149 * For ldd(1) -s, indicate the search paths that'll
150 * be used. If this is a secure application then some
151 * search paths may be ignored, therefore reset the
152 * rpl_libdirs pointer each time so that the
153 * diagnostics related to these unsecure directories
154 * will be output for each image loaded.
159 if (env_info
& ENV_INF_PATHCFG
)
160 fmt
= MSG_INTL(MSG_LDD_PTH_LIBPATHC
);
162 fmt
= MSG_INTL(MSG_LDD_PTH_LIBPATH
);
164 (void) printf(fmt
, rpl_libpath
, config
->c_name
);
166 if (rpl_libdirs
&& (rtld_flags
& RT_FL_SECURE
) &&
167 (search
|| DBG_ENABLED
))
168 remove_alist(&rpl_libdirs
, 1);
170 if (rpl_libdirs
== NULL
) {
172 * If this is a secure application we need to
173 * be selective over what directories we use.
175 (void) expand_paths(lmp
, rpl_libpath
,
176 &rpl_libdirs
, AL_CNT_SEARCH
, mode
,
179 dalpp
= &rpl_libdirs
;
184 * Initialize the permanent (LD_LIBRARY_PATH) search path list.
185 * This can only originate from a configuration file. To be
186 * consistent with the debugging display of DEFENV (above),
187 * always call Dbg_libs_path().
191 (LA_SER_LIBPATH
| LA_SER_CONFIG
| PD_FLG_UNIQUE
);
193 DBG_CALL(Dbg_libs_path(lml
, prm_libpath
, mode
,
197 * For ldd(1) -s, indicate the search paths that'll
198 * be used. If this is a secure application then some
199 * search paths may be ignored, therefore reset the
200 * prm_libdirs pointer each time so that the
201 * diagnostics related to these unsecure directories
202 * will be output for each image loaded.
205 (void) printf(MSG_INTL(MSG_LDD_PTH_LIBPATHC
),
206 prm_libpath
, config
->c_name
);
207 if (prm_libdirs
&& (rtld_flags
& RT_FL_SECURE
) &&
208 (search
|| DBG_ENABLED
))
209 remove_alist(&prm_libdirs
, 1);
211 if (prm_libdirs
== NULL
) {
213 * If this is a secure application we need to
214 * be selective over what directories we use.
216 (void) expand_paths(lmp
, prm_libpath
,
217 &prm_libdirs
, AL_CNT_SEARCH
, mode
,
220 dalpp
= &prm_libdirs
;
225 * Initialize the runpath search path list. To be consistent
226 * with the debugging display of DEFENV (above), always call
230 DBG_CALL(Dbg_libs_path(lml
, RPATH(lmp
), LA_SER_RUNPATH
,
234 * For ldd(1) -s, indicate the search paths that'll
235 * be used. If this is a secure application then some
236 * search paths may be ignored, therefore reset the
237 * runlist pointer each time so that the diagnostics
238 * related to these unsecure directories will be
239 * output for each image loaded.
242 (void) printf(MSG_INTL(MSG_LDD_PTH_RUNPATH
),
243 RPATH(lmp
), NAME(lmp
));
244 if (RLIST(lmp
) && (rtld_flags
& RT_FL_SECURE
) &&
245 (search
|| DBG_ENABLED
))
246 remove_alist(&RLIST(lmp
), 1);
248 if (RLIST(lmp
) == NULL
) {
250 * If this is a secure application we need to
251 * be selective over what directories we use.
253 (void) expand_paths(lmp
, RPATH(lmp
),
254 &RLIST(lmp
), AL_CNT_SEARCH
, LA_SER_RUNPATH
,
262 * If we have been requested to load an audit library through a
263 * DT_DEPAUDIT entry, then we treat this the same way that we
264 * handle a library that has been specified via a DT_NEEDED
265 * entry -- we check the default directories and not the
266 * secure directories.
268 if ((FLAGS1(lmp
) & FL1_RT_NODEFLIB
) == 0) {
269 if ((rtld_flags
& RT_FL_SECURE
) &&
270 ((flags
& FLG_RT_PRELOAD
) ||
271 ((flags
& FLG_RT_AUDIT
) && !(FLAGS1(lmp
) &
273 dalpp
= LM_SECURE_DIRS(lmp
)();
275 dalpp
= LM_DEFAULT_DIRS(lmp
)();
279 * For ldd(1) -s, indicate the default paths that'll be used.
281 if (dalpp
&& (search
|| DBG_ENABLED
))
282 print_default_dirs(lml
, *dalpp
, search
);
291 * Get the next directory in the search rules path. The search path "cookie"
292 * provided by the caller (sdp) maintains the state of a search in progress.
294 * Typically, a search consists of a series of rules that govern the order of
295 * a search (ie. LD_LIBRARY_PATH, followed by RPATHS, followed by defaults).
296 * Each rule can establish a corresponding series of path names, which are
297 * maintained as an Alist. The index within this Alist determines the present
301 get_next_dir(Spath_desc
*sdp
, Rt_map
*lmp
, uint_t flags
)
304 * Make sure there are still rules to process.
306 while (*sdp
->sp_rule
) {
310 * If an Alist for this rule already exists, use if, otherwise
311 * obtain an Alist for this rule. Providing the Alist has
312 * content, and the present Alist index is less than the number
313 * of Alist members, return the associated path name descriptor.
315 if ((sdp
->sp_dalpp
|| ((sdp
->sp_dalpp
=
316 get_dir_list(*sdp
->sp_rule
, lmp
, flags
)) != NULL
)) &&
317 ((alp
= *sdp
->sp_dalpp
) != NULL
) &&
318 (alist_nitems(alp
) > sdp
->sp_idx
)) {
319 return (alist_item(alp
, sdp
->sp_idx
++));
323 * If no Alist for this rule exists, or if this is the last
324 * element of this Alist, reset the Alist pointer and index,
325 * and prepare for the next rule.
328 sdp
->sp_dalpp
= NULL
;
333 * All rules and search paths have been exhausted.
339 * Process a directory (runpath) or filename (needed or filter) string looking
340 * for tokens to expand. Allocate a new buffer for the string.
343 expand(char **name
, size_t *len
, char **list
, uint_t orig
, uint_t omit
,
346 char _name
[PATH_MAX
];
347 char *token
= NULL
, *oname
, *ename
, *optr
, *_optr
, *nptr
, *_list
;
348 size_t olen
= 0, nlen
= 0, _len
;
351 Lm_list
*lml
= LIST(lmp
);
353 optr
= _optr
= oname
= ename
= *name
;
357 while ((olen
< *len
) && (nlen
< PATH_MAX
)) {
360 if ((*optr
!= '$') || ((olen
- *len
) == 1)) {
362 * When expanding paths while a configuration file
363 * exists that contains directory information, determine
364 * whether the path contains "./". If so, we'll resolve
365 * the path later to remove these relative entries.
367 if ((rtld_flags
& RT_FL_DIRCFG
) &&
368 (orig
& LA_SER_MASK
) && (*optr
== '/') &&
369 (optr
!= oname
) && (*(optr
- 1) == '.'))
370 flags
|= TKN_DOTSLASH
;
377 * Copy any string we've presently passed over to the new
380 if ((_len
= (optr
- _optr
)) != 0) {
381 if ((nlen
+= _len
) < PATH_MAX
) {
382 (void) strncpy(nptr
, _optr
, _len
);
385 eprintf(lml
, ERR_FATAL
,
386 MSG_INTL(MSG_ERR_EXPAND1
), NAME(lmp
),
393 * Skip the token delimiter and determine if a reserved token
400 if (strncmp(optr
, MSG_ORIG(MSG_TKN_ORIGIN
),
401 MSG_TKN_ORIGIN_SIZE
) == 0) {
402 token
= (char *)MSG_ORIG(MSG_TKN_ORIGIN
);
405 * $ORIGIN expansion is required. Determine this
406 * objects basename. Expansion of $ORIGIN is allowed
407 * for secure applications but must be checked by the
408 * caller to insure the expanded path matches a
409 * registered secure name.
411 if (((omit
& PD_TKN_ORIGIN
) == 0) &&
412 (((_len
= DIRSZ(lmp
)) != 0) ||
413 ((_len
= fullpath(lmp
, 0)) != 0))) {
414 if ((nlen
+= _len
) < PATH_MAX
) {
416 ORIGNAME(lmp
), _len
);
418 olen
+= MSG_TKN_ORIGIN_SIZE
;
419 optr
+= MSG_TKN_ORIGIN_SIZE
;
420 _flags
|= PD_TKN_ORIGIN
;
422 eprintf(lml
, ERR_FATAL
,
423 MSG_INTL(MSG_ERR_EXPAND1
),
429 } else if (strncmp(optr
, MSG_ORIG(MSG_TKN_PLATFORM
),
430 MSG_TKN_PLATFORM_SIZE
) == 0) {
433 if (FLAGS1(lmp
) & FL1_RT_ALTCAP
)
434 scapset
= alt_scapset
;
436 scapset
= org_scapset
;
438 token
= (char *)MSG_ORIG(MSG_TKN_PLATFORM
);
441 * $PLATFORM expansion required.
443 if (((omit
& PD_TKN_PLATFORM
) == 0) &&
444 ((scapset
->sc_plat
== NULL
) &&
445 (scapset
->sc_platsz
== 0)))
446 platform_name(scapset
);
448 if (((omit
& PD_TKN_PLATFORM
) == 0) &&
450 nlen
+= scapset
->sc_platsz
;
451 if (nlen
< PATH_MAX
) {
452 (void) strncpy(nptr
, scapset
->sc_plat
,
454 nptr
= nptr
+ scapset
->sc_platsz
;
455 olen
+= MSG_TKN_PLATFORM_SIZE
;
456 optr
+= MSG_TKN_PLATFORM_SIZE
;
457 _flags
|= PD_TKN_PLATFORM
;
459 eprintf(lml
, ERR_FATAL
,
460 MSG_INTL(MSG_ERR_EXPAND1
),
466 } else if (strncmp(optr
, MSG_ORIG(MSG_TKN_MACHINE
),
467 MSG_TKN_MACHINE_SIZE
) == 0) {
470 if (FLAGS1(lmp
) & FL1_RT_ALTCAP
)
471 scapset
= alt_scapset
;
473 scapset
= org_scapset
;
475 token
= (char *)MSG_ORIG(MSG_TKN_MACHINE
);
478 * $MACHINE expansion required.
480 if (((omit
& PD_TKN_MACHINE
) == 0) &&
481 ((scapset
->sc_mach
== NULL
) &&
482 (scapset
->sc_machsz
== 0)))
483 machine_name(scapset
);
485 if (((omit
& PD_TKN_MACHINE
) == 0) &&
487 nlen
+= scapset
->sc_machsz
;
488 if (nlen
< PATH_MAX
) {
489 (void) strncpy(nptr
, scapset
->sc_mach
,
491 nptr
= nptr
+ scapset
->sc_machsz
;
492 olen
+= MSG_TKN_MACHINE_SIZE
;
493 optr
+= MSG_TKN_MACHINE_SIZE
;
494 _flags
|= PD_TKN_MACHINE
;
496 eprintf(lml
, ERR_FATAL
,
497 MSG_INTL(MSG_ERR_EXPAND1
),
503 } else if (strncmp(optr
, MSG_ORIG(MSG_TKN_OSNAME
),
504 MSG_TKN_OSNAME_SIZE
) == 0) {
505 token
= (char *)MSG_ORIG(MSG_TKN_OSNAME
);
508 * $OSNAME expansion required. This is established
509 * from the sysname[] returned by uname(2).
511 if (((omit
& PD_TKN_OSNAME
) == 0) && (uts
== NULL
))
514 if (((omit
& PD_TKN_OSNAME
) == 0) &&
515 (uts
&& uts
->uts_osnamesz
)) {
516 if ((nlen
+= uts
->uts_osnamesz
) < PATH_MAX
) {
517 (void) strncpy(nptr
, uts
->uts_osname
,
519 nptr
= nptr
+ uts
->uts_osnamesz
;
520 olen
+= MSG_TKN_OSNAME_SIZE
;
521 optr
+= MSG_TKN_OSNAME_SIZE
;
522 _flags
|= PD_TKN_OSNAME
;
524 eprintf(lml
, ERR_FATAL
,
525 MSG_INTL(MSG_ERR_EXPAND1
),
531 } else if (strncmp(optr
, MSG_ORIG(MSG_TKN_OSREL
),
532 MSG_TKN_OSREL_SIZE
) == 0) {
533 token
= (char *)MSG_ORIG(MSG_TKN_OSREL
);
536 * $OSREL expansion required. This is established
537 * from the release[] returned by uname(2).
539 if (((omit
& PD_TKN_OSREL
) == 0) && (uts
== 0))
542 if (((omit
& PD_TKN_OSREL
) == 0) &&
543 (uts
&& uts
->uts_osrelsz
)) {
544 if ((nlen
+= uts
->uts_osrelsz
) < PATH_MAX
) {
545 (void) strncpy(nptr
, uts
->uts_osrel
,
547 nptr
= nptr
+ uts
->uts_osrelsz
;
548 olen
+= MSG_TKN_OSREL_SIZE
;
549 optr
+= MSG_TKN_OSREL_SIZE
;
550 _flags
|= PD_TKN_OSREL
;
552 eprintf(lml
, ERR_FATAL
,
553 MSG_INTL(MSG_ERR_EXPAND1
),
559 } else if ((strncmp(optr
, MSG_ORIG(MSG_TKN_ISALIST
),
560 MSG_TKN_ISALIST_SIZE
) == 0)) {
562 token
= (char *)MSG_ORIG(MSG_TKN_ISALIST
);
565 * $ISALIST expansion required. When accompanied with
566 * a list pointer, this routine updates that pointer
567 * with the new list of potential candidates. Without
568 * this list pointer, only the first expansion is
569 * provided. NOTE, that two $ISLIST expansions within
570 * the same path aren't supported.
572 if ((omit
& PD_TKN_ISALIST
) || isaflag
++)
577 if (ok
&& (isa
== NULL
))
578 isa
= conv_isalist();
580 if (ok
&& isa
&& isa
->isa_listsz
) {
581 size_t no
, mlen
, tlen
, hlen
= olen
- 1;
583 Isa_opt
*opt
= isa
->isa_opt
;
585 if ((nlen
+= opt
->isa_namesz
) < PATH_MAX
) {
586 (void) strncpy(nptr
, opt
->isa_name
,
588 nptr
= nptr
+ opt
->isa_namesz
;
589 olen
+= MSG_TKN_ISALIST_SIZE
;
590 optr
+= MSG_TKN_ISALIST_SIZE
;
591 _flags
|= PD_TKN_ISALIST
;
593 eprintf(lml
, ERR_FATAL
,
594 MSG_INTL(MSG_ERR_EXPAND1
),
601 mlen
= ((hlen
+ tlen
) *
602 (isa
->isa_optno
- 1)) +
603 isa
->isa_listsz
- opt
->isa_namesz
+
606 malloc(mlen
)) == NULL
)
609 for (no
= 1, opt
++; no
< isa
->isa_optno
;
611 (void) strncpy(lptr
, *name
,
617 lptr
= lptr
+ opt
->isa_namesz
;
618 (void) strncpy(lptr
, optr
,
624 (void) strcpy(lptr
, *list
);
630 } else if (strncmp(optr
, MSG_ORIG(MSG_TKN_CAPABILITY
),
631 MSG_TKN_CAPABILITY_SIZE
) == 0) {
632 char *bptr
= nptr
- 1;
633 char *eptr
= optr
+ MSG_TKN_CAPABILITY_SIZE
;
634 token
= (char *)MSG_ORIG(MSG_TKN_CAPABILITY
);
637 * $CAPABILITY expansion required. Expansion is only
638 * allowed for non-simple path names (must contain a
639 * '/'), with the token itself being the last element
640 * of the path. Therefore, all we need do is test the
641 * existence of the string "/$CAPABILITY\0".
643 if (((omit
& PD_TKN_CAP
) == 0) &&
644 ((bptr
> _name
) && (*bptr
== '/') &&
645 ((*eptr
== '\0') || (*eptr
== ':')))) {
647 * Decrement the present pointer so that the
648 * directories trailing "/" gets nuked later.
651 olen
+= MSG_TKN_CAPABILITY_SIZE
;
652 optr
+= MSG_TKN_CAPABILITY_SIZE
;
653 _flags
|= PD_TKN_CAP
;
656 } else if (strncmp(optr
, MSG_ORIG(MSG_TKN_HWCAP
),
657 MSG_TKN_HWCAP_SIZE
) == 0) {
658 char *bptr
= nptr
- 1;
659 char *eptr
= optr
+ MSG_TKN_HWCAP_SIZE
;
660 token
= (char *)MSG_ORIG(MSG_TKN_HWCAP
);
663 * $HWCAP expansion required. This token has been
664 * superseeded by $CAPABILITY. For compatibility with
665 * older environments, only expand this token when hard-
666 * ware capability information is available. This
667 * expansion is only allowed for non-simple path names
668 * (must contain a '/'), with the token itself being the
669 * last element of the path. Therefore, all we need do
670 * is test the existence of the string "/$HWCAP\0".
672 if (((omit
& PD_TKN_CAP
) == 0) &&
673 (rtld_flags2
& RT_FL2_HWCAP
) &&
674 ((bptr
> _name
) && (*bptr
== '/') &&
675 ((*eptr
== '\0') || (*eptr
== ':')))) {
677 * Decrement the present pointer so that the
678 * directories trailing "/" gets nuked later.
681 olen
+= MSG_TKN_HWCAP_SIZE
;
682 optr
+= MSG_TKN_HWCAP_SIZE
;
683 _flags
|= PD_TKN_CAP
;
688 * If reserved token was not found, copy the
696 * If a reserved token was found, and could not be expanded,
697 * diagnose the error condition.
703 char buf
[PATH_MAX
], *str
;
706 * Note, the original string we're expanding
707 * might contain a number of ':' separated
708 * paths. Isolate the path we're processing to
709 * provide a more precise error diagnostic.
711 if (str
= strchr(oname
, ':')) {
712 size_t slen
= str
- oname
;
714 (void) strncpy(buf
, oname
, slen
);
720 eprintf(lml
, ERR_FATAL
,
721 MSG_INTL(MSG_ERR_EXPAND2
), NAME(lmp
),
730 * First make sure the current length is shorter than PATH_MAX. We may
731 * arrive here if the given path contains '$' characters which are not
732 * the lead of a reserved token.
734 if (nlen
>= PATH_MAX
) {
735 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_ERR_EXPAND1
), NAME(lmp
),
741 * If any ISALIST processing has occurred not only do we return the
742 * expanded node we're presently working on, but we can also update the
743 * remaining list so that it is effectively prepended with this node
744 * expanded to all remaining ISALIST options. Note that we can only
745 * handle one ISALIST per node. For more than one ISALIST to be
746 * processed we'd need a better algorithm than above to replace the
747 * newly generated list. Whether we want to encourage the number of
748 * path name permutations this would provide is another question. So,
749 * for now if more than one ISALIST is encountered we return the
750 * original node untouched.
752 if (isa
&& isaflag
) {
757 flags
&= ~PD_TKN_ISALIST
;
758 if ((nptr
= (char *)stravl_insert(*name
, 0,
759 (*len
+ 1), 1)) == NULL
)
767 * Copy any remaining string. Terminate the new string with a null as
768 * this string can be displayed via debugging diagnostics.
770 if ((_len
= (optr
- _optr
)) != 0) {
771 if ((nlen
+= _len
) < PATH_MAX
) {
772 (void) strncpy(nptr
, _optr
, _len
);
775 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_ERR_EXPAND1
),
783 * A path that has been expanded is typically used to create full
784 * path names for objects that will be opened. The final path name is
785 * resolved to simplify it, and set the stage for possible $ORIGIN
786 * processing. Therefore, it's usually unnecessary to resolve the path
787 * at this point. However, if a configuration file, containing
788 * directory information is in use, then we might need to lookup this
789 * path in the configuration file. To keep the number of path name
790 * resolutions to a minimum, only resolve paths that contain "./". The
791 * use of "$ORIGIN/../lib" will probably only match a configuration file
792 * entry after resolution.
794 if (list
&& (rtld_flags
& RT_FL_DIRCFG
) && (flags
& TKN_DOTSLASH
)) {
797 if ((len
= resolvepath(_name
, _name
, (PATH_MAX
- 1))) >= 0) {
800 flags
|= PD_TKN_RESOLVED
;
805 * Allocate a new string if necessary.
807 * If any form of token expansion, or string resolution has occurred,
808 * the storage must be allocated for the new string.
810 * If we're processing a substring, for example, any string besides the
811 * last string within a search path "A:B:C", then this substring needs
812 * to be isolated with a null terminator. However, if this search path
813 * was created from a previous ISALIST expansion, then all strings must
814 * be allocated, as the isalist expansion will be freed after expansion
817 if ((nptr
= (char *)stravl_insert(_name
, 0, (nlen
+ 1), 1)) == NULL
)
821 return (flags
? flags
: TKN_NONE
);
825 * Determine whether a path name is secure.
828 is_path_secure(char *opath
, Rt_map
*clmp
, uint_t info
, uint_t flags
)
832 char buffer
[PATH_MAX
], *npath
= NULL
;
833 Lm_list
*lml
= LIST(clmp
);
837 * If a path name originates from a configuration file, use it. The use
838 * of a configuration file is already validated for secure applications,
839 * so if we're using a configuration file, we must be able to use all
842 if (info
& LA_SER_CONFIG
)
845 if ((info
& LA_SER_MASK
) == 0) {
849 * If the path name specifies a file (rather than a directory),
850 * peel off the file before making the comparison.
852 str
= strrchr(opath
, '/');
855 * Carry out some initial security checks.
857 * . a simple file name (one containing no "/") is fine, as
858 * this file name will be combined with search paths to
859 * determine the complete path. Note, a secure application
860 * may provide a configuration file, and this can only be
861 * a full path name (PN_FLG_FULLPATH).
862 * . a full path (one starting with "/") is fine, provided
863 * this path name isn't a preload/audit path.
864 * . provided $ORIGIN expansion has not been employed, the
865 * above categories of path are deemed secure.
867 if ((((str
== 0) && ((info
& PD_FLG_FULLPATH
) == 0)) ||
868 ((*opath
== '/') && (str
!= opath
) &&
869 ((info
& PD_FLG_EXTLOAD
) == 0))) &&
870 ((flags
& PD_TKN_ORIGIN
) == 0))
874 * Determine the directory name of the present path.
878 npath
= (char *)MSG_ORIG(MSG_STR_SLASH
);
882 if ((size
= str
- opath
) >= PATH_MAX
)
885 (void) strncpy(buffer
, opath
, size
);
891 * If $ORIGIN processing has been employed, then allow
892 * any directory that has already been used to satisfy
893 * other dependencies, to be used.
895 if ((flags
& PD_TKN_ORIGIN
) &&
896 pnavl_recorded(&spavl
, npath
, 0, NULL
)) {
897 DBG_CALL(Dbg_libs_insecure(lml
, npath
, 1));
903 * A search path, i.e., RPATH, configuration file path, etc. is
904 * used as is. Exceptions to this are:
907 * . any $ORIGIN expansion, unless used by a setuid ld.so.1
908 * to find its own dependencies, or the path name has
909 * already been used to find other dependencies.
910 * . any relative path.
912 if (((info
& LA_SER_LIBPATH
) == 0) && (*opath
== '/') &&
913 ((flags
& PD_TKN_ORIGIN
) == 0))
917 * If $ORIGIN processing is requested, allow a setuid ld.so.1
918 * to use this path for its own dependencies. Allow the
919 * application to use this path name only if the path name has
920 * already been used to locate other dependencies.
922 if (flags
& PD_TKN_ORIGIN
) {
923 if ((lml
->lm_flags
& LML_FLG_RTLDLM
) &&
926 else if (pnavl_recorded(&spavl
, opath
, 0, NULL
)) {
927 DBG_CALL(Dbg_libs_insecure(lml
, opath
, 1));
931 npath
= (char *)opath
;
935 * Determine whether the present directory is trusted.
938 salpp
= LM_SECURE_DIRS(LIST(clmp
)->lm_head
)();
939 for (ALIST_TRAVERSE(*salpp
, idx
, pdp
)) {
940 if (strcmp(npath
, pdp
->pd_pname
) == 0)
946 * The path is insecure, so depending on the caller, provide a
947 * diagnostic. Preloaded, or audit libraries generate a warning, as
948 * the process will run without them.
950 if (info
& PD_FLG_EXTLOAD
) {
951 if (lml
->lm_flags
& LML_FLG_TRC_ENABLE
) {
952 if ((FLAGS1(clmp
) & FL1_RT_LDDSTUB
) == 0)
953 (void) printf(MSG_INTL(MSG_LDD_FIL_ILLEGAL
),
956 eprintf(lml
, ERR_WARNING
, MSG_INTL(MSG_SEC_ILLEGAL
),
963 * Explicit file references are fatal.
965 if ((info
& LA_SER_MASK
) == 0) {
966 if (lml
->lm_flags
& LML_FLG_TRC_ENABLE
) {
968 if ((FLAGS1(clmp
) & FL1_RT_LDDSTUB
) == 0) {
970 (LML_FLG_TRC_VERBOSE
| LML_FLG_TRC_SEARCH
))
972 MSG_INTL(MSG_LDD_FIL_FIND
),
975 if (((rtld_flags
& RT_FL_SILENCERR
) == 0) ||
976 (lml
->lm_flags
& LML_FLG_TRC_VERBOSE
))
978 MSG_INTL(MSG_LDD_FIL_ILLEGAL
),
983 eprintf(lml
, ERR_FATAL
, MSG_INTL(MSG_SYS_OPEN
), opath
,
989 DBG_CALL(Dbg_libs_insecure(lml
, opath
, 0));
990 if ((lml
->lm_flags
& LML_FLG_TRC_SEARCH
) &&
991 ((FLAGS1(clmp
) & FL1_RT_LDDSTUB
) == 0))
992 (void) printf(MSG_INTL(MSG_LDD_PTH_IGNORE
), opath
);
998 * Determine whether a path already exists within the callers Pnode list.
1000 inline static uint_t
1001 is_path_unique(Alist
*alp
, const char *path
)
1006 for (ALIST_TRAVERSE(alp
, idx
, pdp
)) {
1007 if (pdp
->pd_plen
&& (strcmp(pdp
->pd_pname
, path
) == 0))
1008 return (PD_FLG_DUPLICAT
);
1014 * Expand one or more path names. This routine is called for all path strings,
1015 * i.e., NEEDED, rpaths, default search paths, configuration file search paths,
1016 * filtees, etc. The path may be a single path name, or a colon separated list
1017 * of path names. Each individual path name is processed for possible reserved
1018 * token expansion. All string nodes are maintained in allocated memory
1019 * (regardless of whether they are constant (":"), or token expanded) to
1020 * simplify path name descriptor removal.
1022 * The info argument passes in auxiliary information regarding the callers
1023 * intended use of the path names. This information may be maintained in the
1024 * path name descriptor element produced to describe the path name (i.e.,
1025 * LA_SER_LIBPATH etc.), or may be used to determine additional security or
1026 * diagnostic processing.
1029 expand_paths(Rt_map
*clmp
, const char *list
, Alist
**alpp
, Aliste alni
,
1030 uint_t orig
, uint_t omit
)
1032 char *str
, *olist
= 0, *nlist
= (char *)list
;
1033 int fnull
= FALSE
; /* TRUE if empty final path segment seen */
1036 for (str
= nlist
; *nlist
|| fnull
; str
= nlist
) {
1044 if ((*nlist
== ':') || fnull
) {
1045 /* If not a final null segment, check following one */
1046 fnull
= !(fnull
|| *(nlist
+ 1));
1052 * When the shell sees a null PATH segment, it
1053 * treats it as if it were the cwd (.). We mimic
1054 * this behavior for LD_LIBRARY_PATH and runpaths
1055 * (mainly for backwards compatibility with previous
1056 * behavior). For other paths, this makes no sense,
1057 * so we simply ignore the segment.
1059 if (!(orig
& (LA_SER_LIBPATH
| LA_SER_RUNPATH
)))
1060 continue; /* Process next segment */
1062 str
= (char *)MSG_ORIG(MSG_FMT_CWD
);
1063 len
= MSG_FMT_CWD_SIZE
;
1069 while (*nlist
&& (*nlist
!= ':') && (*nlist
!= ';')) {
1071 tkns
|= PD_FLG_PNSLASH
;
1075 /* Check for a following final null segment */
1076 fnull
= (*nlist
== ':') && !*(nlist
+ 1);
1082 * Expand the captured string. Besides expanding the
1083 * present path/file entry, we may have a new list to
1084 * deal with (ISALIST expands to multiple new entries).
1089 if ((_tkns
= expand(&str
, &len
, &elist
, orig
, omit
,
1096 * If this a secure application, validation of the expanded
1097 * path name may be necessary.
1099 if ((rtld_flags
& RT_FL_SECURE
) &&
1100 (is_path_secure(str
, clmp
, orig
, tkns
) == 0))
1104 * If required, ensure that the string is unique. For search
1105 * paths such as LD_LIBRARY_PATH, users often inherit multiple
1106 * paths which result in unnecessary duplication. Note, if
1107 * we're debugging, any duplicate entry is retained and flagged
1108 * so that the entry can be diagnosed later as part of unused
1111 if (orig
& PD_FLG_UNIQUE
) {
1114 tracing
= LIST(clmp
)->lm_flags
&
1115 (LML_FLG_TRC_UNREF
| LML_FLG_TRC_UNUSED
);
1116 tkns
|= is_path_unique(*alpp
, str
);
1119 * Note, use the debug strings rpl_debug and prm_debug
1120 * as an indicator that debugging has been requested,
1121 * rather than DBG_ENABLE(), as the initial use of
1122 * LD_LIBRARY_PATH occurs in preparation for loading
1123 * our debugging library.
1125 if ((tkns
& PD_FLG_DUPLICAT
) && (tracing
== 0) &&
1126 (rpl_debug
== 0) && (prm_debug
== 0))
1131 * Create a new pathname descriptor.
1133 if ((pdp
= alist_append(alpp
, NULL
, sizeof (Pdesc
),
1137 pdp
->pd_pname
= str
;
1139 pdp
->pd_flags
= (orig
& LA_SER_MASK
) | (tkns
& PD_MSK_INHERIT
);
1142 * If token expansion occurred, maintain the original string.
1143 * This string can be used to provide a more informative error
1144 * diagnostic for a file that fails to load, or for displaying
1145 * unused search paths.
1147 if ((tkns
& PD_MSK_EXPAND
) && ((pdp
->pd_oname
=
1148 stravl_insert(ostr
, 0, (olen
+ 1), 1)) == NULL
))
1152 * Now that any duplication of the original string has occurred,
1153 * release any previous old listing.
1155 if (elist
&& (elist
!= nlist
)) {
1157 nlist
= olist
= elist
;
1164 * If no paths could be determined (perhaps because of security), then
1165 * indicate a failure.
1167 return (pdp
!= NULL
);
1171 * Establish an objects fully resolved path.
1173 * When $ORIGIN was first introduced, the expansion of a relative path name was
1174 * deferred until it was required. However now we insure a full path name is
1175 * always created - things like the analyzer wish to rely on librtld_db
1176 * returning a full path. The overhead of this is perceived to be low,
1177 * providing the associated libc version of getcwd is available (see 4336878).
1178 * This getcwd() was ported back to Solaris 8.1.
1181 fullpath(Rt_map
*lmp
, Fdesc
*fdp
)
1186 * Determine whether this path name is already resolved.
1188 if (fdp
&& (fdp
->fd_flags
& FLG_FD_RESOLVED
)) {
1190 * If the resolved path differed from the original name, the
1191 * resolved path would have been recorded as the fd_pname.
1192 * Steal this path name from the file descriptor. Otherwise,
1193 * the path name is the same as the name of this object.
1196 PATHNAME(lmp
) = fdp
->fd_pname
;
1198 PATHNAME(lmp
) = NAME(lmp
);
1201 * If this path name has not yet been resolved, resolve the
1204 char _path
[PATH_MAX
];
1208 if (fdp
&& fdp
->fd_pname
)
1209 PATHNAME(lmp
) = fdp
->fd_pname
;
1211 PATHNAME(lmp
) = NAME(lmp
);
1213 name
= path
= PATHNAME(lmp
);
1214 size
= strlen(name
);
1216 if (path
[0] != '/') {
1218 * If we can't determine the current directory (possible
1219 * if too many files are open - EMFILE), or if the
1220 * created path is too big, simply revert back to the
1221 * initial path name.
1223 if (getcwd(_path
, (PATH_MAX
- 2 - size
)) != NULL
) {
1224 (void) strcat(_path
, MSG_ORIG(MSG_STR_SLASH
));
1225 (void) strcat(_path
, name
);
1227 size
= strlen(path
);
1232 * See if the path name can be reduced further.
1234 if ((rsize
= resolvepath(path
, _path
, (PATH_MAX
- 1))) > 0) {
1235 _path
[rsize
] = '\0';
1241 * If the path name is different from the original, duplicate it
1242 * so that it is available in a core file. If the duplication
1243 * fails simply leave the original path name alone.
1245 if ((PATHNAME(lmp
) =
1246 stravl_insert(path
, 0, (size
+ 1), 0)) == NULL
)
1247 PATHNAME(lmp
) = name
;
1250 name
= ORIGNAME(lmp
) = PATHNAME(lmp
);
1253 * Establish the directory name size - this also acts as a flag that the
1254 * directory name has been computed.
1256 DIRSZ(lmp
) = strrchr(name
, '/') - name
;
1257 return (DIRSZ(lmp
));