17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
55aefb655Srie  * Common Development and Distribution License (the "License").
65aefb655Srie  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
215aefb655Srie 
227c478bd9Sstevel@tonic-gate /*
2308278a5eSRod Evans  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include	<sys/mman.h>
287c478bd9Sstevel@tonic-gate #include	<sys/types.h>
297c478bd9Sstevel@tonic-gate #include	<sys/stat.h>
307c478bd9Sstevel@tonic-gate #include	<fcntl.h>
317c478bd9Sstevel@tonic-gate #include	<limits.h>
327c478bd9Sstevel@tonic-gate #include	<stdio.h>
337c478bd9Sstevel@tonic-gate #include	<string.h>
345aefb655Srie #include	<rtc.h>
355aefb655Srie #include	<debug.h>
365aefb655Srie #include	<conv.h>
377c478bd9Sstevel@tonic-gate #include	"_rtld.h"
387c478bd9Sstevel@tonic-gate #include	"msg.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate static Config	_config = { 0 };
41247b82a1SRod Evans Config		*config = &_config;
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate  * Validate a configuration file.
457c478bd9Sstevel@tonic-gate  */
467c478bd9Sstevel@tonic-gate static void
elf_config_validate(Addr addr,Rtc_head * head,Rt_map * lmp)475aefb655Srie elf_config_validate(Addr addr, Rtc_head *head, Rt_map *lmp)
487c478bd9Sstevel@tonic-gate {
495aefb655Srie 	Lm_list		*lml = LIST(lmp);
507c478bd9Sstevel@tonic-gate 	const char	*str, *strtbl = config->c_strtbl;
517c478bd9Sstevel@tonic-gate 	Rtc_obj		*obj;
527c478bd9Sstevel@tonic-gate 	Rtc_dir		*dirtbl;
537c478bd9Sstevel@tonic-gate 	Rtc_file	*filetbl;
54cb511613SAli Bahrami 	rtld_stat_t	status;
557c478bd9Sstevel@tonic-gate 	int		err;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	/*
587c478bd9Sstevel@tonic-gate 	 * If this configuration file is for a specific application make sure
597c478bd9Sstevel@tonic-gate 	 * we've been invoked by the application.  Note that we only check the
607c478bd9Sstevel@tonic-gate 	 * basename component of the application as the original application
617c478bd9Sstevel@tonic-gate 	 * and its cached equivalent are never going to have the same pathnames.
627c478bd9Sstevel@tonic-gate 	 * Also, we use PATHNAME() and not NAME() - this catches things like vi
637c478bd9Sstevel@tonic-gate 	 * that exec shells using execv(/usr/bin/ksh, sh ...).
647c478bd9Sstevel@tonic-gate 	 */
657c478bd9Sstevel@tonic-gate 	if (head->ch_app) {
6656deab07SRod Evans 		char		*_str, *_cname, *cname;
6756deab07SRod Evans 		const char	*aname = PATHNAME(lmp);
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate 		obj = (Rtc_obj *)(head->ch_app + addr);
707c478bd9Sstevel@tonic-gate 		cname = _cname = (char *)(strtbl + obj->co_name);
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 		if ((_str = strrchr(aname, '/')) != NULL)
737c478bd9Sstevel@tonic-gate 			aname = ++_str;
747c478bd9Sstevel@tonic-gate 		if ((_str = strrchr(cname, '/')) != NULL)
757c478bd9Sstevel@tonic-gate 			cname = ++_str;
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 		if (strcmp(aname, cname)) {
787c478bd9Sstevel@tonic-gate 			/*
797c478bd9Sstevel@tonic-gate 			 * It's possible a user is trying to ldd(1) an alternate
807c478bd9Sstevel@tonic-gate 			 * shared object and point to a configuration file that
817c478bd9Sstevel@tonic-gate 			 * the shared object is part of.  In this case ignore
827c478bd9Sstevel@tonic-gate 			 * any mismatch name warnings.
837c478bd9Sstevel@tonic-gate 			 */
845aefb655Srie 			if ((lml->lm_flags & LML_FLG_TRC_ENABLE) &&
857c478bd9Sstevel@tonic-gate 			    ((FLAGS1(lmp) & FL1_RT_LDDSTUB) == 0)) {
865aefb655Srie 				eprintf(lml, ERR_WARNING,
875aefb655Srie 				    MSG_INTL(MSG_CONF_APP), config->c_name,
885aefb655Srie 				    _cname);
897c478bd9Sstevel@tonic-gate 				return;
907c478bd9Sstevel@tonic-gate 			}
917c478bd9Sstevel@tonic-gate 		}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 		/*
947c478bd9Sstevel@tonic-gate 		 * If we have a valid alternative application reset its original
957c478bd9Sstevel@tonic-gate 		 * name for possible $ORIGIN processing.
967c478bd9Sstevel@tonic-gate 		 */
977c478bd9Sstevel@tonic-gate 		if ((FLAGS1(lmp) & FL1_RT_LDDSTUB) == 0) {
987c478bd9Sstevel@tonic-gate 			ORIGNAME(lmp) = _cname;
997c478bd9Sstevel@tonic-gate 			DIRSZ(lmp) = cname - _cname - 1;
1007c478bd9Sstevel@tonic-gate 		}
1017c478bd9Sstevel@tonic-gate 	}
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate 	/*
1047c478bd9Sstevel@tonic-gate 	 * If alternative objects are specified traverse the directories
1057c478bd9Sstevel@tonic-gate 	 * specified in the configuration file, if any directory is newer than
1067c478bd9Sstevel@tonic-gate 	 * the time it was recorded in the cache then continue to inspect its
1077c478bd9Sstevel@tonic-gate 	 * files.  Any file determined newer than its configuration recording
1087c478bd9Sstevel@tonic-gate 	 * questions the the use of any alternative objects.  The intent here
1097c478bd9Sstevel@tonic-gate 	 * is to make sure no-one abuses a configuration as a means of static
1107c478bd9Sstevel@tonic-gate 	 * linking.
1117c478bd9Sstevel@tonic-gate 	 */
1127c478bd9Sstevel@tonic-gate 	for (dirtbl = (Rtc_dir *)(head->ch_dir + addr);
1137c478bd9Sstevel@tonic-gate 	    dirtbl->cd_obj; dirtbl++) {
1147c478bd9Sstevel@tonic-gate 		/*
1157c478bd9Sstevel@tonic-gate 		 * Skip directories that provide no files - this also catches
1167c478bd9Sstevel@tonic-gate 		 * RTC_OBJ_NOEXIST directories.
1177c478bd9Sstevel@tonic-gate 		 */
1187c478bd9Sstevel@tonic-gate 		filetbl = (Rtc_file *)(dirtbl->cd_file + addr);
11967d74cc3SToomas Soome 		if (filetbl->cf_obj == 0)
1207c478bd9Sstevel@tonic-gate 			continue;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 		/*
1237c478bd9Sstevel@tonic-gate 		 * Skip directories that haven't provided real, dumped files.
1247c478bd9Sstevel@tonic-gate 		 */
1257c478bd9Sstevel@tonic-gate 		obj = (Rtc_obj *)(dirtbl->cd_obj + addr);
1267c478bd9Sstevel@tonic-gate 		if ((obj->co_flags & (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) !=
1277c478bd9Sstevel@tonic-gate 		    (RTC_OBJ_DUMP | RTC_OBJ_REALPTH))
1287c478bd9Sstevel@tonic-gate 			continue;
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 		str = strtbl + obj->co_name;
1317c478bd9Sstevel@tonic-gate 
132cb511613SAli Bahrami 		if (rtld_stat(str, &status) != 0) {
1337c478bd9Sstevel@tonic-gate 			err = errno;
1345aefb655Srie 			eprintf(lml, ERR_WARNING, MSG_INTL(MSG_CONF_DSTAT),
1357c478bd9Sstevel@tonic-gate 			    config->c_name, str, strerror(err));
1367c478bd9Sstevel@tonic-gate 			continue;
1377c478bd9Sstevel@tonic-gate 		}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 		if (status.st_mtime == obj->co_info)
1407c478bd9Sstevel@tonic-gate 			continue;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 		/*
1437c478bd9Sstevel@tonic-gate 		 * The system directory is newer than the configuration files
1447c478bd9Sstevel@tonic-gate 		 * entry, start checking any dumped files.
1457c478bd9Sstevel@tonic-gate 		 */
1467c478bd9Sstevel@tonic-gate 		for (; filetbl->cf_obj; filetbl++) {
1477c478bd9Sstevel@tonic-gate 			obj = (Rtc_obj *)(filetbl->cf_obj + addr);
1487c478bd9Sstevel@tonic-gate 			str = strtbl + obj->co_name;
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 			/*
1517c478bd9Sstevel@tonic-gate 			 * Skip any files that aren't real, dumped files.
1527c478bd9Sstevel@tonic-gate 			 */
1537c478bd9Sstevel@tonic-gate 			if ((obj->co_flags &
1547c478bd9Sstevel@tonic-gate 			    (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) !=
1557c478bd9Sstevel@tonic-gate 			    (RTC_OBJ_DUMP | RTC_OBJ_REALPTH))
1567c478bd9Sstevel@tonic-gate 				continue;
1577c478bd9Sstevel@tonic-gate 
158cb511613SAli Bahrami 			if (rtld_stat(str, &status) != 0) {
1597c478bd9Sstevel@tonic-gate 				err = errno;
1605aefb655Srie 				eprintf(lml, ERR_WARNING,
1615aefb655Srie 				    MSG_INTL(MSG_CONF_FSTAT), config->c_name,
1625aefb655Srie 				    str, strerror(err));
1637c478bd9Sstevel@tonic-gate 				continue;
1647c478bd9Sstevel@tonic-gate 			}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 			/*
1677c478bd9Sstevel@tonic-gate 			 * If the files size is different somethings been
1687c478bd9Sstevel@tonic-gate 			 * changed.
1697c478bd9Sstevel@tonic-gate 			 */
1707c478bd9Sstevel@tonic-gate 			if (status.st_size != obj->co_info) {
1715aefb655Srie 				eprintf(lml, ERR_WARNING,
1725aefb655Srie 				    MSG_INTL(MSG_CONF_FCMP), config->c_name,
1735aefb655Srie 				    str);
1747c478bd9Sstevel@tonic-gate 			}
1757c478bd9Sstevel@tonic-gate 		}
1767c478bd9Sstevel@tonic-gate 	}
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate 
179247b82a1SRod Evans /*
180247b82a1SRod Evans  * Process a configuration file.
181247b82a1SRod Evans  *
182247b82a1SRod Evans  * A configuration file can be specified using the LD_CONFIG environment
183247b82a1SRod Evans  * variable, from a DT_CONFIG string recorded in the executable (see ld(1) -c),
184*fec04708SRichard Lowe  * or in the case of a crle(1) dumped image, the file is "fabricated" to a
185247b82a1SRod Evans  * configuration file that may have been associated with the dumped image.  In
186247b82a1SRod Evans  * the absence of any of these techniques, a default configuration file is used.
187247b82a1SRod Evans  *
188*fec04708SRichard Lowe  * The LD_CONFIG variable takes precedence, unless the application is secure
189*fec04708SRichard Lowe  * (see ld.so.1(1), issetugid(2)), in which case the environment variable is
190*fec04708SRichard Lowe  * ignored (see ld_generic_env()).
191247b82a1SRod Evans  *
192247b82a1SRod Evans  * A DT_CONFIG string is honored, even if the application is secure.  However,
193247b82a1SRod Evans  * the path name follows the same rules as RUNPATH's, which must be a full path
194247b82a1SRod Evans  * name with no use of $ORIGIN.
195247b82a1SRod Evans  */
1967c478bd9Sstevel@tonic-gate int
elf_config(Rt_map * lmp)197*fec04708SRichard Lowe elf_config(Rt_map *lmp)
1987c478bd9Sstevel@tonic-gate {
199c13de8f6Sab 	Rtc_id		*id;
2007c478bd9Sstevel@tonic-gate 	Rtc_head	*head;
2017c478bd9Sstevel@tonic-gate 	int		fd, features = 0;
202cb511613SAli Bahrami 	rtld_stat_t	status;
2037c478bd9Sstevel@tonic-gate 	Addr		addr;
204247b82a1SRod Evans 	const char	*str;
205247b82a1SRod Evans 	char		path[PATH_MAX];
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	/*
208247b82a1SRod Evans 	 * If we're dealing with an alternative application, fabricate the need
209247b82a1SRod Evans 	 * for a $ORIGIN/ld.config.app-name configuration file.
2107c478bd9Sstevel@tonic-gate 	 */
211247b82a1SRod Evans 	if (rtld_flags & RT_FL_CONFAPP) {
212247b82a1SRod Evans 		if ((str = strrchr(PATHNAME(lmp), '/')) != NULL)
213247b82a1SRod Evans 			str++;
214247b82a1SRod Evans 		else
215247b82a1SRod Evans 			str = PATHNAME(lmp);
2167c478bd9Sstevel@tonic-gate 
217247b82a1SRod Evans 		(void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_ORG_CONFIG), str);
218247b82a1SRod Evans 		str = path;
219247b82a1SRod Evans 	} else
220247b82a1SRod Evans 		str = config->c_name;
2217c478bd9Sstevel@tonic-gate 
222247b82a1SRod Evans 	/*
223247b82a1SRod Evans 	 * If a configuration file name is known, expand and verify the name.
224247b82a1SRod Evans 	 */
225247b82a1SRod Evans 	if (str) {
226247b82a1SRod Evans 		size_t	size = strlen(str);
227247b82a1SRod Evans 		char	*estr = (char *)str;
228247b82a1SRod Evans 		uint_t	tkns;
2297c478bd9Sstevel@tonic-gate 
230247b82a1SRod Evans 		/*
231247b82a1SRod Evans 		 * Expand any configuration string.
232247b82a1SRod Evans 		 */
233247b82a1SRod Evans 		if ((tkns = expand(&estr, &size, 0, 0,
23408278a5eSRod Evans 		    (PD_TKN_ISALIST | PD_TKN_CAP), lmp)) == 0)
235247b82a1SRod Evans 			return (0);
2367c478bd9Sstevel@tonic-gate 
237247b82a1SRod Evans 		/*
238247b82a1SRod Evans 		 * If this is a secure application, validate the configuration
239247b82a1SRod Evans 		 * file path name.  Ignore any untrustworthy path name, and
240247b82a1SRod Evans 		 * fall through to pick up the defaults.
241247b82a1SRod Evans 		 */
242247b82a1SRod Evans 		if ((rtld_flags & RT_FL_SECURE) &&
24356deab07SRod Evans 		    (is_path_secure(estr, lmp, PD_FLG_FULLPATH, tkns) == 0))
244247b82a1SRod Evans 			str = NULL;
245247b82a1SRod Evans 		else
246247b82a1SRod Evans 			str = (const char *)estr;
247247b82a1SRod Evans 	}
2487c478bd9Sstevel@tonic-gate 
249247b82a1SRod Evans 	/*
250247b82a1SRod Evans 	 * If a configuration file has not been specified try opening up the
251247b82a1SRod Evans 	 * default.
252247b82a1SRod Evans 	 */
253247b82a1SRod Evans 	if (str == NULL) {
254247b82a1SRod Evans #if	defined(_ELF64)
255247b82a1SRod Evans 		str = MSG_ORIG(MSG_PTH_CONFIG_64);
256247b82a1SRod Evans #else
257247b82a1SRod Evans 		str = MSG_ORIG(MSG_PTH_CONFIG);
258247b82a1SRod Evans #endif
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 	config->c_name = str;
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	/*
2637c478bd9Sstevel@tonic-gate 	 * If we can't open the configuration file return silently.
2647c478bd9Sstevel@tonic-gate 	 */
2657c478bd9Sstevel@tonic-gate 	if ((fd = open(str, O_RDONLY, 0)) == -1)
2667c478bd9Sstevel@tonic-gate 		return (DBG_CONF_PRCFAIL);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/*
2697c478bd9Sstevel@tonic-gate 	 * Determine the configuration file size and map the file.
2707c478bd9Sstevel@tonic-gate 	 */
271cb511613SAli Bahrami 	(void) rtld_fstat(fd, &status);
2727c478bd9Sstevel@tonic-gate 	if (status.st_size < sizeof (Rtc_head)) {
2737c478bd9Sstevel@tonic-gate 		(void) close(fd);
2747c478bd9Sstevel@tonic-gate 		return (DBG_CONF_CORRUPT);
2757c478bd9Sstevel@tonic-gate 	}
2767c478bd9Sstevel@tonic-gate 	if ((addr = (Addr)mmap(0, status.st_size, PROT_READ, MAP_SHARED,
2777c478bd9Sstevel@tonic-gate 	    fd, 0)) == (Addr)MAP_FAILED) {
2787c478bd9Sstevel@tonic-gate 		(void) close(fd);
2797c478bd9Sstevel@tonic-gate 		return (DBG_CONF_PRCFAIL);
2807c478bd9Sstevel@tonic-gate 	}
281c13de8f6Sab 	(void) close(fd);
282c13de8f6Sab 
283c13de8f6Sab 	/*
284c13de8f6Sab 	 * If we have an Rtc_id block at the beginning, then validate it
285c13de8f6Sab 	 * and advance the address to the Rtc_head. If not, then trust
286c13de8f6Sab 	 * that the file is compatible with us and move ahead (there is
287c13de8f6Sab 	 * some error checking for Rtc_head below as well).
288c13de8f6Sab 	 */
289c13de8f6Sab 	id = (Rtc_id *) addr;
290c13de8f6Sab 	if (RTC_ID_TEST(id)) {
291c13de8f6Sab 		addr += sizeof (*id);
292c13de8f6Sab 		status.st_size -= sizeof (*id);
293c13de8f6Sab 		if (status.st_size < sizeof (Rtc_head))
294c13de8f6Sab 			return (DBG_CONF_CORRUPT);
295c13de8f6Sab 		if ((id->id_class != M_CLASS) || (id->id_data != M_DATA) ||
296c13de8f6Sab 		    (id->id_machine != M_MACH))
297c13de8f6Sab 			return (DBG_CONF_ABIMISMATCH);
298c13de8f6Sab 	}
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	config->c_bgn = addr;
3017c478bd9Sstevel@tonic-gate 	config->c_end = addr + status.st_size;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	head = (Rtc_head *)addr;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	/*
3067c478bd9Sstevel@tonic-gate 	 * Make sure we can handle this version of the configuration file.
3077c478bd9Sstevel@tonic-gate 	 */
3087c478bd9Sstevel@tonic-gate 	if (head->ch_version > RTC_VER_CURRENT)
3097c478bd9Sstevel@tonic-gate 		return (DBG_CONF_VERSION);
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	/*
3127c478bd9Sstevel@tonic-gate 	 * When crle(1) creates a temporary configuration file the
3137c478bd9Sstevel@tonic-gate 	 * RTC_HDR_IGNORE flag is set.  Thus the mapping of the configuration
3147c478bd9Sstevel@tonic-gate 	 * file is taken into account but not its content.
3157c478bd9Sstevel@tonic-gate 	 */
3167c478bd9Sstevel@tonic-gate 	if (head->ch_cnflags & RTC_HDR_IGNORE)
3177c478bd9Sstevel@tonic-gate 		return (DBG_CONF_IGNORE);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	/*
3207c478bd9Sstevel@tonic-gate 	 * Apply any new default library pathname.
3217c478bd9Sstevel@tonic-gate 	 */
3227c478bd9Sstevel@tonic-gate 	if (head->ch_edlibpath) {
3237c478bd9Sstevel@tonic-gate 		str = (const char *)(head->ch_edlibpath + addr);
3247c478bd9Sstevel@tonic-gate 		if ((head->ch_cnflags & RTC_HDR_UPM) == 0) {
3257c478bd9Sstevel@tonic-gate #if	defined(_ELF64)
3265aefb655Srie 			str = conv_config_upm(str, MSG_ORIG(MSG_PTH_USRLIB_64),
3277c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_PTH_LIB_64), MSG_PTH_LIB_64_SIZE);
3287c478bd9Sstevel@tonic-gate #else
3295aefb655Srie 			str = conv_config_upm(str, MSG_ORIG(MSG_PTH_USRLIB),
3307c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_PTH_LIB), MSG_PTH_LIB_SIZE);
3317c478bd9Sstevel@tonic-gate #endif
3327c478bd9Sstevel@tonic-gate 		}
33356deab07SRod Evans 		if (expand_paths(lmp, str, &elf_def_dirs, AL_CNT_SEARCH,
33467d74cc3SToomas Soome 		    (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_CAP) != 0)
33556deab07SRod Evans 			features |= CONF_EDLIBPATH;
3367c478bd9Sstevel@tonic-gate 	}
3377c478bd9Sstevel@tonic-gate 	if (head->ch_eslibpath) {
3387c478bd9Sstevel@tonic-gate 		str = (const char *)(head->ch_eslibpath + addr);
3397c478bd9Sstevel@tonic-gate 		if ((head->ch_cnflags & RTC_HDR_UPM) == 0) {
3407c478bd9Sstevel@tonic-gate #if	defined(_ELF64)
3415aefb655Srie 			str = conv_config_upm(str,
3427c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_PTH_USRLIBSE_64),
3437c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_PTH_LIBSE_64), MSG_PTH_LIBSE_64_SIZE);
3447c478bd9Sstevel@tonic-gate #else
3455aefb655Srie 			str = conv_config_upm(str, MSG_ORIG(MSG_PTH_USRLIBSE),
3467c478bd9Sstevel@tonic-gate 			    MSG_ORIG(MSG_PTH_LIBSE), MSG_PTH_LIBSE_SIZE);
3477c478bd9Sstevel@tonic-gate #endif
3487c478bd9Sstevel@tonic-gate 		}
34956deab07SRod Evans 		if (expand_paths(lmp, str, &elf_sec_dirs, AL_CNT_SEARCH,
35067d74cc3SToomas Soome 		    (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_CAP) != 0)
35156deab07SRod Evans 			features |= CONF_ESLIBPATH;
3527c478bd9Sstevel@tonic-gate 	}
353*fec04708SRichard Lowe 
3547c478bd9Sstevel@tonic-gate 	/*
3557c478bd9Sstevel@tonic-gate 	 * Apply any environment variables.  This attribute was added with
3567c478bd9Sstevel@tonic-gate 	 * RTC_VER_THREE.
3577c478bd9Sstevel@tonic-gate 	 */
3587c478bd9Sstevel@tonic-gate 	if ((head->ch_version >= RTC_VER_THREE) && head->ch_env &&
3597c478bd9Sstevel@tonic-gate 	    (!(rtld_flags & RT_FL_NOENVCFG))) {
3607c478bd9Sstevel@tonic-gate 		if (readenv_config((Rtc_env *)(head->ch_env + addr),
361*fec04708SRichard Lowe 		    addr) != 0)
3627c478bd9Sstevel@tonic-gate 			return (-1);
3637c478bd9Sstevel@tonic-gate 		features |= CONF_ENVS;
3647c478bd9Sstevel@tonic-gate 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	/*
3677c478bd9Sstevel@tonic-gate 	 * Determine whether filter/filtee associations are available.
3687c478bd9Sstevel@tonic-gate 	 */
3697c478bd9Sstevel@tonic-gate 	if ((head->ch_version >= RTC_VER_FOUR) && head->ch_fltr &&
3707c478bd9Sstevel@tonic-gate 	    (!(rtld_flags2 & RT_FL2_NOFLTCFG))) {
3717c478bd9Sstevel@tonic-gate 		rtld_flags2 |= RT_FL2_FLTCFG;
3727c478bd9Sstevel@tonic-gate 		config->c_fltr = (Rtc_fltr *)(head->ch_fltr + addr);
3737c478bd9Sstevel@tonic-gate 		config->c_flte = (Rtc_flte *)(head->ch_flte + addr);
3747c478bd9Sstevel@tonic-gate 		features |= CONF_FLTR;
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
3777c478bd9Sstevel@tonic-gate 	/*
3787c478bd9Sstevel@tonic-gate 	 * Determine whether directory configuration is available.
3797c478bd9Sstevel@tonic-gate 	 */
3807c478bd9Sstevel@tonic-gate 	if ((!(rtld_flags & RT_FL_NODIRCFG)) && head->ch_hash) {
3817c478bd9Sstevel@tonic-gate 		config->c_hashtbl = (Word *)(head->ch_hash + addr);
3827c478bd9Sstevel@tonic-gate 		config->c_hashchain = &config->c_hashtbl[2 +
3837c478bd9Sstevel@tonic-gate 		    config->c_hashtbl[0]];
3847c478bd9Sstevel@tonic-gate 		config->c_objtbl = (Rtc_obj *)(head->ch_obj + addr);
3857c478bd9Sstevel@tonic-gate 		config->c_strtbl = (const char *)(head->ch_str + addr);
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate 		rtld_flags |= RT_FL_DIRCFG;
3887c478bd9Sstevel@tonic-gate 		features |= CONF_DIRCFG;
3897c478bd9Sstevel@tonic-gate 	}
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate 	/*
3927c478bd9Sstevel@tonic-gate 	 * Determine whether alternative objects are specified or an object
3937c478bd9Sstevel@tonic-gate 	 * reservation area is required.  If the reservation can't be completed
3947c478bd9Sstevel@tonic-gate 	 * (either because the configuration information is out-of-date, or the
3957c478bd9Sstevel@tonic-gate 	 * the reservation can't be allocated), then alternative objects are
3967c478bd9Sstevel@tonic-gate 	 * ignored.
3977c478bd9Sstevel@tonic-gate 	 */
3987c478bd9Sstevel@tonic-gate 	if ((!(rtld_flags & (RT_FL_NODIRCFG | RT_FL_NOOBJALT))) &&
3997c478bd9Sstevel@tonic-gate 	    (head->ch_cnflags & RTC_HDR_ALTER)) {
4007c478bd9Sstevel@tonic-gate 		rtld_flags |= RT_FL_OBJALT;
4017c478bd9Sstevel@tonic-gate 		features |= CONF_OBJALT;
4027c478bd9Sstevel@tonic-gate 
4037c478bd9Sstevel@tonic-gate 		elf_config_validate(addr, head, lmp);
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 		if (head->ch_resbgn) {
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 			if (((config->c_bgn <= head->ch_resbgn) &&
4087c478bd9Sstevel@tonic-gate 			    (config->c_bgn >= head->ch_resend)) ||
4095aefb655Srie 			    (nu_map(LIST(lmp),
4105aefb655Srie 			    (caddr_t)(uintptr_t)head->ch_resbgn,
4117c478bd9Sstevel@tonic-gate 			    (head->ch_resend - head->ch_resbgn), PROT_NONE,
4127c478bd9Sstevel@tonic-gate 			    MAP_FIXED | MAP_PRIVATE) == MAP_FAILED))
4137c478bd9Sstevel@tonic-gate 				return (-1);
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 			rtld_flags |= RT_FL_MEMRESV;
4167c478bd9Sstevel@tonic-gate 			features |= CONF_MEMRESV;
4177c478bd9Sstevel@tonic-gate 		}
4187c478bd9Sstevel@tonic-gate 	}
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	return (features);
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate /*
4247c478bd9Sstevel@tonic-gate  * Determine whether the given file exists in the configuration file.
4257c478bd9Sstevel@tonic-gate  */
4267c478bd9Sstevel@tonic-gate Rtc_obj *
elf_config_ent(const char * name,Word hash,int id,const char ** alternate)4277c478bd9Sstevel@tonic-gate elf_config_ent(const char *name, Word hash, int id, const char **alternate)
4287c478bd9Sstevel@tonic-gate {
4297c478bd9Sstevel@tonic-gate 	Word		bkt, ndx;
4307c478bd9Sstevel@tonic-gate 	const char	*str;
4317c478bd9Sstevel@tonic-gate 	Rtc_obj		*obj;
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	bkt = hash % config->c_hashtbl[0];
4347c478bd9Sstevel@tonic-gate 	ndx = config->c_hashtbl[2 + bkt];
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	while (ndx) {
4377c478bd9Sstevel@tonic-gate 		obj = config->c_objtbl + ndx;
4387c478bd9Sstevel@tonic-gate 		str = config->c_strtbl + obj->co_name;
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 		if ((obj->co_hash != hash) || (strcmp(name, str) != 0) ||
4417c478bd9Sstevel@tonic-gate 		    (id && (id != obj->co_id))) {
4427c478bd9Sstevel@tonic-gate 			ndx = config->c_hashchain[ndx];
4437c478bd9Sstevel@tonic-gate 			continue;
4447c478bd9Sstevel@tonic-gate 		}
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 		if ((obj->co_flags & RTC_OBJ_ALTER) && alternate)
4477c478bd9Sstevel@tonic-gate 			*alternate = config->c_strtbl + obj->co_alter;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 		return (obj);
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 	return (0);
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate /*
4557c478bd9Sstevel@tonic-gate  * Determine whether a filter and filtee string pair exists in the configuration
4567c478bd9Sstevel@tonic-gate  * file.  If so, return the cached filtees that are associated with this pair as
45756deab07SRod Evans  * an Alist.
4587c478bd9Sstevel@tonic-gate  */
45956deab07SRod Evans void
elf_config_flt(Lm_list * lml,const char * filter,const char * string,Alist ** alpp,Aliste alni)46056deab07SRod Evans elf_config_flt(Lm_list *lml, const char *filter, const char *string,
46156deab07SRod Evans     Alist **alpp, Aliste alni)
4627c478bd9Sstevel@tonic-gate {
463247b82a1SRod Evans 	Rtc_fltr	*fltrtbl;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	for (fltrtbl = (Rtc_fltr *)config->c_fltr; fltrtbl->fr_filter;
4667c478bd9Sstevel@tonic-gate 	    fltrtbl++) {
4677c478bd9Sstevel@tonic-gate 		Rtc_flte	*fltetbl;
4687c478bd9Sstevel@tonic-gate 		const char	*fltr, *str;
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 		fltr = config->c_strtbl + fltrtbl->fr_filter;
4717c478bd9Sstevel@tonic-gate 		str = config->c_strtbl + fltrtbl->fr_string;
4727c478bd9Sstevel@tonic-gate 		if (strcmp(filter, fltr) || strcmp(string, str))
4737c478bd9Sstevel@tonic-gate 			continue;
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 		/*
47656deab07SRod Evans 		 * Create a path descriptor for each filtee associated with this
4777c478bd9Sstevel@tonic-gate 		 * filter/filtee string pair.  Note, no expansion of filtee
4787c478bd9Sstevel@tonic-gate 		 * entries is called for, as any original expansion would have
4797c478bd9Sstevel@tonic-gate 		 * been carried out before they were recorded in the
4807c478bd9Sstevel@tonic-gate 		 * configuration file.
4817c478bd9Sstevel@tonic-gate 		 */
4827c478bd9Sstevel@tonic-gate 		/* LINTED */
4837c478bd9Sstevel@tonic-gate 		for (fltetbl = (Rtc_flte *)((char *)config->c_flte +
4847c478bd9Sstevel@tonic-gate 		    fltrtbl->fr_filtee); fltetbl->fe_filtee; fltetbl++) {
4857c478bd9Sstevel@tonic-gate 			const char	*flte;
48656deab07SRod Evans 			Pdesc		*pdp;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 			flte = config->c_strtbl + fltetbl->fe_filtee;
4897c478bd9Sstevel@tonic-gate 
490dde769a2SRod Evans 			if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc),
49156deab07SRod Evans 			    alni)) == NULL)
49256deab07SRod Evans 				return;
4937c478bd9Sstevel@tonic-gate 
49456deab07SRod Evans 			pdp->pd_pname = (char *)flte;
49556deab07SRod Evans 			pdp->pd_plen = strlen(flte) + 1;
49656deab07SRod Evans 			pdp->pd_flags = LA_SER_CONFIG;
4977c478bd9Sstevel@tonic-gate 
49856deab07SRod Evans 			DBG_CALL(Dbg_file_filter(lml, fltr, flte, 1));
4997c478bd9Sstevel@tonic-gate 		}
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate }
502