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 /* 23*08278a5eSRod 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 }; 417c478bd9Sstevel@tonic-gate Config *config = &_config; 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate /* 447c478bd9Sstevel@tonic-gate * Validate a configuration file. 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate static void 477c478bd9Sstevel@tonic-gate 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); 119247b82a1SRod Evans if (filetbl->cf_obj == NULL) 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), 184247b82a1SRod Evans * or in the case of a crle() 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 * 188247b82a1SRod Evans * The LD_CONFIG variable take precedence, unless the application is secure, in 189247b82a1SRod Evans * which case the environment variable is ignored (see ld_generic_env()). 190247b82a1SRod Evans * 191247b82a1SRod Evans * A DT_CONFIG string is honored, even if the application is secure. However, 192247b82a1SRod Evans * the path name follows the same rules as RUNPATH's, which must be a full path 193247b82a1SRod Evans * name with no use of $ORIGIN. 194247b82a1SRod Evans */ 1957c478bd9Sstevel@tonic-gate int 1967c478bd9Sstevel@tonic-gate elf_config(Rt_map *lmp, int aout) 1977c478bd9Sstevel@tonic-gate { 198c13de8f6Sab196087 Rtc_id *id; 1997c478bd9Sstevel@tonic-gate Rtc_head *head; 2007c478bd9Sstevel@tonic-gate int fd, features = 0; 201cb511613SAli Bahrami rtld_stat_t status; 2027c478bd9Sstevel@tonic-gate Addr addr; 203247b82a1SRod Evans const char *str; 204247b82a1SRod Evans char path[PATH_MAX]; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate /* 207247b82a1SRod Evans * If we're dealing with an alternative application, fabricate the need 208247b82a1SRod Evans * for a $ORIGIN/ld.config.app-name configuration file. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate if (rtld_flags & RT_FL_CONFAPP) { 2117c478bd9Sstevel@tonic-gate if ((str = strrchr(PATHNAME(lmp), '/')) != NULL) 2127c478bd9Sstevel@tonic-gate str++; 2137c478bd9Sstevel@tonic-gate else 2147c478bd9Sstevel@tonic-gate str = PATHNAME(lmp); 2157c478bd9Sstevel@tonic-gate 216247b82a1SRod Evans (void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_ORG_CONFIG), str); 217247b82a1SRod Evans str = path; 218247b82a1SRod Evans } else 219247b82a1SRod Evans str = config->c_name; 220247b82a1SRod Evans 221247b82a1SRod Evans /* 222247b82a1SRod Evans * If a configuration file name is known, expand and verify the name. 223247b82a1SRod Evans */ 224247b82a1SRod Evans if (str) { 225247b82a1SRod Evans size_t size = strlen(str); 226247b82a1SRod Evans char *estr = (char *)str; 227247b82a1SRod Evans uint_t tkns; 228247b82a1SRod Evans 229247b82a1SRod Evans /* 230247b82a1SRod Evans * Expand any configuration string. 231247b82a1SRod Evans */ 232247b82a1SRod Evans if ((tkns = expand(&estr, &size, 0, 0, 233*08278a5eSRod Evans (PD_TKN_ISALIST | PD_TKN_CAP), lmp)) == 0) 234247b82a1SRod Evans return (0); 235247b82a1SRod Evans 236247b82a1SRod Evans /* 237247b82a1SRod Evans * If this is a secure application, validate the configuration 238247b82a1SRod Evans * file path name. Ignore any untrustworthy path name, and 239247b82a1SRod Evans * fall through to pick up the defaults. 240247b82a1SRod Evans */ 241247b82a1SRod Evans if ((rtld_flags & RT_FL_SECURE) && 24256deab07SRod Evans (is_path_secure(estr, lmp, PD_FLG_FULLPATH, tkns) == 0)) 243247b82a1SRod Evans str = NULL; 244247b82a1SRod Evans else 245247b82a1SRod Evans str = (const char *)estr; 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate 248247b82a1SRod Evans /* 249247b82a1SRod Evans * If a configuration file has not been specified try opening up the 250247b82a1SRod Evans * default. 251247b82a1SRod Evans */ 252247b82a1SRod Evans if (str == NULL) { 253247b82a1SRod Evans #if defined(_ELF64) 254247b82a1SRod Evans str = MSG_ORIG(MSG_PTH_CONFIG_64); 255247b82a1SRod Evans #else 256247b82a1SRod Evans str = MSG_ORIG(MSG_PTH_CONFIG); 257247b82a1SRod Evans #endif 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate config->c_name = str; 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* 2627c478bd9Sstevel@tonic-gate * If we can't open the configuration file return silently. 2637c478bd9Sstevel@tonic-gate */ 2647c478bd9Sstevel@tonic-gate if ((fd = open(str, O_RDONLY, 0)) == -1) 2657c478bd9Sstevel@tonic-gate return (DBG_CONF_PRCFAIL); 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * Determine the configuration file size and map the file. 2697c478bd9Sstevel@tonic-gate */ 270cb511613SAli Bahrami (void) rtld_fstat(fd, &status); 2717c478bd9Sstevel@tonic-gate if (status.st_size < sizeof (Rtc_head)) { 2727c478bd9Sstevel@tonic-gate (void) close(fd); 2737c478bd9Sstevel@tonic-gate return (DBG_CONF_CORRUPT); 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate if ((addr = (Addr)mmap(0, status.st_size, PROT_READ, MAP_SHARED, 2767c478bd9Sstevel@tonic-gate fd, 0)) == (Addr)MAP_FAILED) { 2777c478bd9Sstevel@tonic-gate (void) close(fd); 2787c478bd9Sstevel@tonic-gate return (DBG_CONF_PRCFAIL); 2797c478bd9Sstevel@tonic-gate } 280c13de8f6Sab196087 (void) close(fd); 281c13de8f6Sab196087 282c13de8f6Sab196087 /* 283c13de8f6Sab196087 * If we have an Rtc_id block at the beginning, then validate it 284c13de8f6Sab196087 * and advance the address to the Rtc_head. If not, then trust 285c13de8f6Sab196087 * that the file is compatible with us and move ahead (there is 286c13de8f6Sab196087 * some error checking for Rtc_head below as well). 287c13de8f6Sab196087 */ 288c13de8f6Sab196087 id = (Rtc_id *) addr; 289c13de8f6Sab196087 if (RTC_ID_TEST(id)) { 290c13de8f6Sab196087 addr += sizeof (*id); 291c13de8f6Sab196087 status.st_size -= sizeof (*id); 292c13de8f6Sab196087 if (status.st_size < sizeof (Rtc_head)) 293c13de8f6Sab196087 return (DBG_CONF_CORRUPT); 294c13de8f6Sab196087 if ((id->id_class != M_CLASS) || (id->id_data != M_DATA) || 295c13de8f6Sab196087 (id->id_machine != M_MACH)) 296c13de8f6Sab196087 return (DBG_CONF_ABIMISMATCH); 297c13de8f6Sab196087 } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate config->c_bgn = addr; 3007c478bd9Sstevel@tonic-gate config->c_end = addr + status.st_size; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate head = (Rtc_head *)addr; 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* 3057c478bd9Sstevel@tonic-gate * Make sure we can handle this version of the configuration file. 3067c478bd9Sstevel@tonic-gate */ 3077c478bd9Sstevel@tonic-gate if (head->ch_version > RTC_VER_CURRENT) 3087c478bd9Sstevel@tonic-gate return (DBG_CONF_VERSION); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate /* 3117c478bd9Sstevel@tonic-gate * When crle(1) creates a temporary configuration file the 3127c478bd9Sstevel@tonic-gate * RTC_HDR_IGNORE flag is set. Thus the mapping of the configuration 3137c478bd9Sstevel@tonic-gate * file is taken into account but not its content. 3147c478bd9Sstevel@tonic-gate */ 3157c478bd9Sstevel@tonic-gate if (head->ch_cnflags & RTC_HDR_IGNORE) 3167c478bd9Sstevel@tonic-gate return (DBG_CONF_IGNORE); 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate /* 3197c478bd9Sstevel@tonic-gate * Apply any new default library pathname. 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate if (head->ch_edlibpath) { 3227c478bd9Sstevel@tonic-gate str = (const char *)(head->ch_edlibpath + addr); 3237c478bd9Sstevel@tonic-gate #ifndef SGS_PRE_UNIFIED_PROCESS 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 } 3337c478bd9Sstevel@tonic-gate #endif 33456deab07SRod Evans if (expand_paths(lmp, str, &elf_def_dirs, AL_CNT_SEARCH, 335*08278a5eSRod Evans (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_CAP) != NULL) 3367c478bd9Sstevel@tonic-gate features |= CONF_EDLIBPATH; 3377c478bd9Sstevel@tonic-gate } 3387c478bd9Sstevel@tonic-gate if (head->ch_eslibpath) { 3397c478bd9Sstevel@tonic-gate str = (const char *)(head->ch_eslibpath + addr); 3407c478bd9Sstevel@tonic-gate #ifndef SGS_PRE_UNIFIED_PROCESS 3417c478bd9Sstevel@tonic-gate if ((head->ch_cnflags & RTC_HDR_UPM) == 0) { 3427c478bd9Sstevel@tonic-gate #if defined(_ELF64) 3435aefb655Srie str = conv_config_upm(str, 3447c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_PTH_USRLIBSE_64), 3457c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_PTH_LIBSE_64), MSG_PTH_LIBSE_64_SIZE); 3467c478bd9Sstevel@tonic-gate #else 3475aefb655Srie str = conv_config_upm(str, MSG_ORIG(MSG_PTH_USRLIBSE), 3487c478bd9Sstevel@tonic-gate MSG_ORIG(MSG_PTH_LIBSE), MSG_PTH_LIBSE_SIZE); 3497c478bd9Sstevel@tonic-gate #endif 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate #endif 35256deab07SRod Evans if (expand_paths(lmp, str, &elf_sec_dirs, AL_CNT_SEARCH, 353*08278a5eSRod Evans (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_CAP) != NULL) 3547c478bd9Sstevel@tonic-gate features |= CONF_ESLIBPATH; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate #if defined(__sparc) && !defined(_ELF64) 3577c478bd9Sstevel@tonic-gate if (head->ch_adlibpath) { 3587c478bd9Sstevel@tonic-gate str = (const char *)(head->ch_adlibpath + addr); 35956deab07SRod Evans if (expand_paths(lmp, str, &aout_def_dirs, AL_CNT_SEARCH, 360*08278a5eSRod Evans (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_CAP) != NULL) 3617c478bd9Sstevel@tonic-gate features |= CONF_ADLIBPATH; 3627c478bd9Sstevel@tonic-gate } 3637c478bd9Sstevel@tonic-gate if (head->ch_aslibpath) { 3647c478bd9Sstevel@tonic-gate str = (const char *)(head->ch_aslibpath + addr); 36556deab07SRod Evans if (expand_paths(lmp, str, &aout_sec_dirs, AL_CNT_SEARCH, 366*08278a5eSRod Evans (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_CAP) != NULL) 3677c478bd9Sstevel@tonic-gate features |= CONF_ASLIBPATH; 3687c478bd9Sstevel@tonic-gate } 3697c478bd9Sstevel@tonic-gate #endif 3707c478bd9Sstevel@tonic-gate /* 3717c478bd9Sstevel@tonic-gate * Apply any environment variables. This attribute was added with 3727c478bd9Sstevel@tonic-gate * RTC_VER_THREE. 3737c478bd9Sstevel@tonic-gate */ 3747c478bd9Sstevel@tonic-gate if ((head->ch_version >= RTC_VER_THREE) && head->ch_env && 3757c478bd9Sstevel@tonic-gate (!(rtld_flags & RT_FL_NOENVCFG))) { 3767c478bd9Sstevel@tonic-gate if (readenv_config((Rtc_env *)(head->ch_env + addr), 3777c478bd9Sstevel@tonic-gate addr, aout) != 0) 3787c478bd9Sstevel@tonic-gate return (-1); 3797c478bd9Sstevel@tonic-gate features |= CONF_ENVS; 3807c478bd9Sstevel@tonic-gate } 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate /* 3837c478bd9Sstevel@tonic-gate * Determine whether filter/filtee associations are available. 3847c478bd9Sstevel@tonic-gate */ 3857c478bd9Sstevel@tonic-gate if ((head->ch_version >= RTC_VER_FOUR) && head->ch_fltr && 3867c478bd9Sstevel@tonic-gate (!(rtld_flags2 & RT_FL2_NOFLTCFG))) { 3877c478bd9Sstevel@tonic-gate rtld_flags2 |= RT_FL2_FLTCFG; 3887c478bd9Sstevel@tonic-gate config->c_fltr = (Rtc_fltr *)(head->ch_fltr + addr); 3897c478bd9Sstevel@tonic-gate config->c_flte = (Rtc_flte *)(head->ch_flte + addr); 3907c478bd9Sstevel@tonic-gate features |= CONF_FLTR; 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate /* 3947c478bd9Sstevel@tonic-gate * Determine whether directory configuration is available. 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate if ((!(rtld_flags & RT_FL_NODIRCFG)) && head->ch_hash) { 3977c478bd9Sstevel@tonic-gate config->c_hashtbl = (Word *)(head->ch_hash + addr); 3987c478bd9Sstevel@tonic-gate config->c_hashchain = &config->c_hashtbl[2 + 3997c478bd9Sstevel@tonic-gate config->c_hashtbl[0]]; 4007c478bd9Sstevel@tonic-gate config->c_objtbl = (Rtc_obj *)(head->ch_obj + addr); 4017c478bd9Sstevel@tonic-gate config->c_strtbl = (const char *)(head->ch_str + addr); 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate rtld_flags |= RT_FL_DIRCFG; 4047c478bd9Sstevel@tonic-gate features |= CONF_DIRCFG; 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Determine whether alternative objects are specified or an object 4097c478bd9Sstevel@tonic-gate * reservation area is required. If the reservation can't be completed 4107c478bd9Sstevel@tonic-gate * (either because the configuration information is out-of-date, or the 4117c478bd9Sstevel@tonic-gate * the reservation can't be allocated), then alternative objects are 4127c478bd9Sstevel@tonic-gate * ignored. 4137c478bd9Sstevel@tonic-gate */ 4147c478bd9Sstevel@tonic-gate if ((!(rtld_flags & (RT_FL_NODIRCFG | RT_FL_NOOBJALT))) && 4157c478bd9Sstevel@tonic-gate (head->ch_cnflags & RTC_HDR_ALTER)) { 4167c478bd9Sstevel@tonic-gate rtld_flags |= RT_FL_OBJALT; 4177c478bd9Sstevel@tonic-gate features |= CONF_OBJALT; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate elf_config_validate(addr, head, lmp); 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if (head->ch_resbgn) { 4227c478bd9Sstevel@tonic-gate 4237c478bd9Sstevel@tonic-gate if (((config->c_bgn <= head->ch_resbgn) && 4247c478bd9Sstevel@tonic-gate (config->c_bgn >= head->ch_resend)) || 4255aefb655Srie (nu_map(LIST(lmp), 4265aefb655Srie (caddr_t)(uintptr_t)head->ch_resbgn, 4277c478bd9Sstevel@tonic-gate (head->ch_resend - head->ch_resbgn), PROT_NONE, 4287c478bd9Sstevel@tonic-gate MAP_FIXED | MAP_PRIVATE) == MAP_FAILED)) 4297c478bd9Sstevel@tonic-gate return (-1); 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate rtld_flags |= RT_FL_MEMRESV; 4327c478bd9Sstevel@tonic-gate features |= CONF_MEMRESV; 4337c478bd9Sstevel@tonic-gate } 4347c478bd9Sstevel@tonic-gate } 4357c478bd9Sstevel@tonic-gate 4367c478bd9Sstevel@tonic-gate return (features); 4377c478bd9Sstevel@tonic-gate } 4387c478bd9Sstevel@tonic-gate 4397c478bd9Sstevel@tonic-gate /* 4407c478bd9Sstevel@tonic-gate * Determine whether the given file exists in the configuration file. 4417c478bd9Sstevel@tonic-gate */ 4427c478bd9Sstevel@tonic-gate Rtc_obj * 4437c478bd9Sstevel@tonic-gate elf_config_ent(const char *name, Word hash, int id, const char **alternate) 4447c478bd9Sstevel@tonic-gate { 4457c478bd9Sstevel@tonic-gate Word bkt, ndx; 4467c478bd9Sstevel@tonic-gate const char *str; 4477c478bd9Sstevel@tonic-gate Rtc_obj *obj; 4487c478bd9Sstevel@tonic-gate 4497c478bd9Sstevel@tonic-gate bkt = hash % config->c_hashtbl[0]; 4507c478bd9Sstevel@tonic-gate ndx = config->c_hashtbl[2 + bkt]; 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate while (ndx) { 4537c478bd9Sstevel@tonic-gate obj = config->c_objtbl + ndx; 4547c478bd9Sstevel@tonic-gate str = config->c_strtbl + obj->co_name; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate if ((obj->co_hash != hash) || (strcmp(name, str) != 0) || 4577c478bd9Sstevel@tonic-gate (id && (id != obj->co_id))) { 4587c478bd9Sstevel@tonic-gate ndx = config->c_hashchain[ndx]; 4597c478bd9Sstevel@tonic-gate continue; 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate if ((obj->co_flags & RTC_OBJ_ALTER) && alternate) 4637c478bd9Sstevel@tonic-gate *alternate = config->c_strtbl + obj->co_alter; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate return (obj); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate return (0); 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* 4717c478bd9Sstevel@tonic-gate * Determine whether a filter and filtee string pair exists in the configuration 4727c478bd9Sstevel@tonic-gate * file. If so, return the cached filtees that are associated with this pair as 47356deab07SRod Evans * an Alist. 4747c478bd9Sstevel@tonic-gate */ 47556deab07SRod Evans void 47656deab07SRod Evans elf_config_flt(Lm_list *lml, const char *filter, const char *string, 47756deab07SRod Evans Alist **alpp, Aliste alni) 4787c478bd9Sstevel@tonic-gate { 4797c478bd9Sstevel@tonic-gate Rtc_fltr *fltrtbl; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate for (fltrtbl = (Rtc_fltr *)config->c_fltr; fltrtbl->fr_filter; 4827c478bd9Sstevel@tonic-gate fltrtbl++) { 4837c478bd9Sstevel@tonic-gate Rtc_flte *fltetbl; 4847c478bd9Sstevel@tonic-gate const char *fltr, *str; 4857c478bd9Sstevel@tonic-gate 4867c478bd9Sstevel@tonic-gate fltr = config->c_strtbl + fltrtbl->fr_filter; 4877c478bd9Sstevel@tonic-gate str = config->c_strtbl + fltrtbl->fr_string; 4887c478bd9Sstevel@tonic-gate if (strcmp(filter, fltr) || strcmp(string, str)) 4897c478bd9Sstevel@tonic-gate continue; 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate /* 49256deab07SRod Evans * Create a path descriptor for each filtee associated with this 4937c478bd9Sstevel@tonic-gate * filter/filtee string pair. Note, no expansion of filtee 4947c478bd9Sstevel@tonic-gate * entries is called for, as any original expansion would have 4957c478bd9Sstevel@tonic-gate * been carried out before they were recorded in the 4967c478bd9Sstevel@tonic-gate * configuration file. 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate /* LINTED */ 4997c478bd9Sstevel@tonic-gate for (fltetbl = (Rtc_flte *)((char *)config->c_flte + 5007c478bd9Sstevel@tonic-gate fltrtbl->fr_filtee); fltetbl->fe_filtee; fltetbl++) { 5017c478bd9Sstevel@tonic-gate const char *flte; 50256deab07SRod Evans Pdesc *pdp; 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate flte = config->c_strtbl + fltetbl->fe_filtee; 5057c478bd9Sstevel@tonic-gate 506dde769a2SRod Evans if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc), 50756deab07SRod Evans alni)) == NULL) 50856deab07SRod Evans return; 50956deab07SRod Evans 51056deab07SRod Evans pdp->pd_pname = (char *)flte; 51156deab07SRod Evans pdp->pd_plen = strlen(flte) + 1; 51256deab07SRod Evans pdp->pd_flags = LA_SER_CONFIG; 5137c478bd9Sstevel@tonic-gate 5145aefb655Srie DBG_CALL(Dbg_file_filter(lml, fltr, flte, 1)); 5157c478bd9Sstevel@tonic-gate } 5167c478bd9Sstevel@tonic-gate } 5177c478bd9Sstevel@tonic-gate } 518