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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/mman.h> 28 #include <sys/types.h> 29 #include <sys/stat.h> 30 #include <fcntl.h> 31 #include <limits.h> 32 #include <stdio.h> 33 #include <string.h> 34 #include <rtc.h> 35 #include <debug.h> 36 #include <conv.h> 37 #include "_rtld.h" 38 #include "msg.h" 39 40 static Config _config = { 0 }; 41 Config *config = &_config; 42 43 /* 44 * Validate a configuration file. 45 */ 46 static void 47 elf_config_validate(Addr addr, Rtc_head *head, Rt_map *lmp) 48 { 49 Lm_list *lml = LIST(lmp); 50 const char *str, *strtbl = config->c_strtbl; 51 Rtc_obj *obj; 52 Rtc_dir *dirtbl; 53 Rtc_file *filetbl; 54 rtld_stat_t status; 55 int err; 56 57 /* 58 * If this configuration file is for a specific application make sure 59 * we've been invoked by the application. Note that we only check the 60 * basename component of the application as the original application 61 * and its cached equivalent are never going to have the same pathnames. 62 * Also, we use PATHNAME() and not NAME() - this catches things like vi 63 * that exec shells using execv(/usr/bin/ksh, sh ...). 64 */ 65 if (head->ch_app) { 66 char *_str, *_cname, *cname; 67 const char *aname = PATHNAME(lmp); 68 69 obj = (Rtc_obj *)(head->ch_app + addr); 70 cname = _cname = (char *)(strtbl + obj->co_name); 71 72 if ((_str = strrchr(aname, '/')) != NULL) 73 aname = ++_str; 74 if ((_str = strrchr(cname, '/')) != NULL) 75 cname = ++_str; 76 77 if (strcmp(aname, cname)) { 78 /* 79 * It's possible a user is trying to ldd(1) an alternate 80 * shared object and point to a configuration file that 81 * the shared object is part of. In this case ignore 82 * any mismatch name warnings. 83 */ 84 if ((lml->lm_flags & LML_FLG_TRC_ENABLE) && 85 ((FLAGS1(lmp) & FL1_RT_LDDSTUB) == 0)) { 86 eprintf(lml, ERR_WARNING, 87 MSG_INTL(MSG_CONF_APP), config->c_name, 88 _cname); 89 return; 90 } 91 } 92 93 /* 94 * If we have a valid alternative application reset its original 95 * name for possible $ORIGIN processing. 96 */ 97 if ((FLAGS1(lmp) & FL1_RT_LDDSTUB) == 0) { 98 ORIGNAME(lmp) = _cname; 99 DIRSZ(lmp) = cname - _cname - 1; 100 } 101 } 102 103 /* 104 * If alternative objects are specified traverse the directories 105 * specified in the configuration file, if any directory is newer than 106 * the time it was recorded in the cache then continue to inspect its 107 * files. Any file determined newer than its configuration recording 108 * questions the the use of any alternative objects. The intent here 109 * is to make sure no-one abuses a configuration as a means of static 110 * linking. 111 */ 112 for (dirtbl = (Rtc_dir *)(head->ch_dir + addr); 113 dirtbl->cd_obj; dirtbl++) { 114 /* 115 * Skip directories that provide no files - this also catches 116 * RTC_OBJ_NOEXIST directories. 117 */ 118 filetbl = (Rtc_file *)(dirtbl->cd_file + addr); 119 if (filetbl->cf_obj == 0) 120 continue; 121 122 /* 123 * Skip directories that haven't provided real, dumped files. 124 */ 125 obj = (Rtc_obj *)(dirtbl->cd_obj + addr); 126 if ((obj->co_flags & (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) != 127 (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) 128 continue; 129 130 str = strtbl + obj->co_name; 131 132 if (rtld_stat(str, &status) != 0) { 133 err = errno; 134 eprintf(lml, ERR_WARNING, MSG_INTL(MSG_CONF_DSTAT), 135 config->c_name, str, strerror(err)); 136 continue; 137 } 138 139 if (status.st_mtime == obj->co_info) 140 continue; 141 142 /* 143 * The system directory is newer than the configuration files 144 * entry, start checking any dumped files. 145 */ 146 for (; filetbl->cf_obj; filetbl++) { 147 obj = (Rtc_obj *)(filetbl->cf_obj + addr); 148 str = strtbl + obj->co_name; 149 150 /* 151 * Skip any files that aren't real, dumped files. 152 */ 153 if ((obj->co_flags & 154 (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) != 155 (RTC_OBJ_DUMP | RTC_OBJ_REALPTH)) 156 continue; 157 158 if (rtld_stat(str, &status) != 0) { 159 err = errno; 160 eprintf(lml, ERR_WARNING, 161 MSG_INTL(MSG_CONF_FSTAT), config->c_name, 162 str, strerror(err)); 163 continue; 164 } 165 166 /* 167 * If the files size is different somethings been 168 * changed. 169 */ 170 if (status.st_size != obj->co_info) { 171 eprintf(lml, ERR_WARNING, 172 MSG_INTL(MSG_CONF_FCMP), config->c_name, 173 str); 174 } 175 } 176 } 177 } 178 179 /* 180 * Process a configuration file. 181 * 182 * A configuration file can be specified using the LD_CONFIG environment 183 * variable, from a DT_CONFIG string recorded in the executable (see ld(1) -c), 184 * or in the case of a crle() dumped image, the file is "fabricated" to a 185 * configuration file that may have been associated with the dumped image. In 186 * the absence of any of these techniques, a default configuration file is used. 187 * 188 * The LD_CONFIG variable take precedence, unless the application is secure, in 189 * which case the environment variable is ignored (see ld_generic_env()). 190 * 191 * A DT_CONFIG string is honored, even if the application is secure. However, 192 * the path name follows the same rules as RUNPATH's, which must be a full path 193 * name with no use of $ORIGIN. 194 */ 195 int 196 elf_config(Rt_map *lmp, int aout) 197 { 198 Rtc_id *id; 199 Rtc_head *head; 200 int fd, features = 0; 201 rtld_stat_t status; 202 Addr addr; 203 const char *str; 204 char path[PATH_MAX]; 205 206 /* 207 * If we're dealing with an alternative application, fabricate the need 208 * for a $ORIGIN/ld.config.app-name configuration file. 209 */ 210 if (rtld_flags & RT_FL_CONFAPP) { 211 if ((str = strrchr(PATHNAME(lmp), '/')) != NULL) 212 str++; 213 else 214 str = PATHNAME(lmp); 215 216 (void) snprintf(path, PATH_MAX, MSG_ORIG(MSG_ORG_CONFIG), str); 217 str = path; 218 } else 219 str = config->c_name; 220 221 /* 222 * If a configuration file name is known, expand and verify the name. 223 */ 224 if (str) { 225 size_t size = strlen(str); 226 char *estr = (char *)str; 227 uint_t tkns; 228 229 /* 230 * Expand any configuration string. 231 */ 232 if ((tkns = expand(&estr, &size, 0, 0, 233 (PD_TKN_ISALIST | PD_TKN_CAP), lmp)) == 0) 234 return (0); 235 236 /* 237 * If this is a secure application, validate the configuration 238 * file path name. Ignore any untrustworthy path name, and 239 * fall through to pick up the defaults. 240 */ 241 if ((rtld_flags & RT_FL_SECURE) && 242 (is_path_secure(estr, lmp, PD_FLG_FULLPATH, tkns) == 0)) 243 str = NULL; 244 else 245 str = (const char *)estr; 246 } 247 248 /* 249 * If a configuration file has not been specified try opening up the 250 * default. 251 */ 252 if (str == NULL) { 253 #if defined(_ELF64) 254 str = MSG_ORIG(MSG_PTH_CONFIG_64); 255 #else 256 str = MSG_ORIG(MSG_PTH_CONFIG); 257 #endif 258 } 259 config->c_name = str; 260 261 /* 262 * If we can't open the configuration file return silently. 263 */ 264 if ((fd = open(str, O_RDONLY, 0)) == -1) 265 return (DBG_CONF_PRCFAIL); 266 267 /* 268 * Determine the configuration file size and map the file. 269 */ 270 (void) rtld_fstat(fd, &status); 271 if (status.st_size < sizeof (Rtc_head)) { 272 (void) close(fd); 273 return (DBG_CONF_CORRUPT); 274 } 275 if ((addr = (Addr)mmap(0, status.st_size, PROT_READ, MAP_SHARED, 276 fd, 0)) == (Addr)MAP_FAILED) { 277 (void) close(fd); 278 return (DBG_CONF_PRCFAIL); 279 } 280 (void) close(fd); 281 282 /* 283 * If we have an Rtc_id block at the beginning, then validate it 284 * and advance the address to the Rtc_head. If not, then trust 285 * that the file is compatible with us and move ahead (there is 286 * some error checking for Rtc_head below as well). 287 */ 288 id = (Rtc_id *) addr; 289 if (RTC_ID_TEST(id)) { 290 addr += sizeof (*id); 291 status.st_size -= sizeof (*id); 292 if (status.st_size < sizeof (Rtc_head)) 293 return (DBG_CONF_CORRUPT); 294 if ((id->id_class != M_CLASS) || (id->id_data != M_DATA) || 295 (id->id_machine != M_MACH)) 296 return (DBG_CONF_ABIMISMATCH); 297 } 298 299 config->c_bgn = addr; 300 config->c_end = addr + status.st_size; 301 302 head = (Rtc_head *)addr; 303 304 /* 305 * Make sure we can handle this version of the configuration file. 306 */ 307 if (head->ch_version > RTC_VER_CURRENT) 308 return (DBG_CONF_VERSION); 309 310 /* 311 * When crle(1) creates a temporary configuration file the 312 * RTC_HDR_IGNORE flag is set. Thus the mapping of the configuration 313 * file is taken into account but not its content. 314 */ 315 if (head->ch_cnflags & RTC_HDR_IGNORE) 316 return (DBG_CONF_IGNORE); 317 318 /* 319 * Apply any new default library pathname. 320 */ 321 if (head->ch_edlibpath) { 322 str = (const char *)(head->ch_edlibpath + addr); 323 if ((head->ch_cnflags & RTC_HDR_UPM) == 0) { 324 #if defined(_ELF64) 325 str = conv_config_upm(str, MSG_ORIG(MSG_PTH_USRLIB_64), 326 MSG_ORIG(MSG_PTH_LIB_64), MSG_PTH_LIB_64_SIZE); 327 #else 328 str = conv_config_upm(str, MSG_ORIG(MSG_PTH_USRLIB), 329 MSG_ORIG(MSG_PTH_LIB), MSG_PTH_LIB_SIZE); 330 #endif 331 } 332 if (expand_paths(lmp, str, &elf_def_dirs, AL_CNT_SEARCH, 333 (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_CAP) != 0) 334 features |= CONF_EDLIBPATH; 335 } 336 if (head->ch_eslibpath) { 337 str = (const char *)(head->ch_eslibpath + addr); 338 if ((head->ch_cnflags & RTC_HDR_UPM) == 0) { 339 #if defined(_ELF64) 340 str = conv_config_upm(str, 341 MSG_ORIG(MSG_PTH_USRLIBSE_64), 342 MSG_ORIG(MSG_PTH_LIBSE_64), MSG_PTH_LIBSE_64_SIZE); 343 #else 344 str = conv_config_upm(str, MSG_ORIG(MSG_PTH_USRLIBSE), 345 MSG_ORIG(MSG_PTH_LIBSE), MSG_PTH_LIBSE_SIZE); 346 #endif 347 } 348 if (expand_paths(lmp, str, &elf_sec_dirs, AL_CNT_SEARCH, 349 (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_CAP) != 0) 350 features |= CONF_ESLIBPATH; 351 } 352 #if defined(__sparc) && !defined(_ELF64) 353 if (head->ch_adlibpath) { 354 str = (const char *)(head->ch_adlibpath + addr); 355 if (expand_paths(lmp, str, &aout_def_dirs, AL_CNT_SEARCH, 356 (LA_SER_DEFAULT | LA_SER_CONFIG), PD_TKN_CAP) != 0) 357 features |= CONF_ADLIBPATH; 358 } 359 if (head->ch_aslibpath) { 360 str = (const char *)(head->ch_aslibpath + addr); 361 if (expand_paths(lmp, str, &aout_sec_dirs, AL_CNT_SEARCH, 362 (LA_SER_SECURE | LA_SER_CONFIG), PD_TKN_CAP) != 0) 363 features |= CONF_ASLIBPATH; 364 } 365 #endif 366 /* 367 * Apply any environment variables. This attribute was added with 368 * RTC_VER_THREE. 369 */ 370 if ((head->ch_version >= RTC_VER_THREE) && head->ch_env && 371 (!(rtld_flags & RT_FL_NOENVCFG))) { 372 if (readenv_config((Rtc_env *)(head->ch_env + addr), 373 addr, aout) != 0) 374 return (-1); 375 features |= CONF_ENVS; 376 } 377 378 /* 379 * Determine whether filter/filtee associations are available. 380 */ 381 if ((head->ch_version >= RTC_VER_FOUR) && head->ch_fltr && 382 (!(rtld_flags2 & RT_FL2_NOFLTCFG))) { 383 rtld_flags2 |= RT_FL2_FLTCFG; 384 config->c_fltr = (Rtc_fltr *)(head->ch_fltr + addr); 385 config->c_flte = (Rtc_flte *)(head->ch_flte + addr); 386 features |= CONF_FLTR; 387 } 388 389 /* 390 * Determine whether directory configuration is available. 391 */ 392 if ((!(rtld_flags & RT_FL_NODIRCFG)) && head->ch_hash) { 393 config->c_hashtbl = (Word *)(head->ch_hash + addr); 394 config->c_hashchain = &config->c_hashtbl[2 + 395 config->c_hashtbl[0]]; 396 config->c_objtbl = (Rtc_obj *)(head->ch_obj + addr); 397 config->c_strtbl = (const char *)(head->ch_str + addr); 398 399 rtld_flags |= RT_FL_DIRCFG; 400 features |= CONF_DIRCFG; 401 } 402 403 /* 404 * Determine whether alternative objects are specified or an object 405 * reservation area is required. If the reservation can't be completed 406 * (either because the configuration information is out-of-date, or the 407 * the reservation can't be allocated), then alternative objects are 408 * ignored. 409 */ 410 if ((!(rtld_flags & (RT_FL_NODIRCFG | RT_FL_NOOBJALT))) && 411 (head->ch_cnflags & RTC_HDR_ALTER)) { 412 rtld_flags |= RT_FL_OBJALT; 413 features |= CONF_OBJALT; 414 415 elf_config_validate(addr, head, lmp); 416 417 if (head->ch_resbgn) { 418 419 if (((config->c_bgn <= head->ch_resbgn) && 420 (config->c_bgn >= head->ch_resend)) || 421 (nu_map(LIST(lmp), 422 (caddr_t)(uintptr_t)head->ch_resbgn, 423 (head->ch_resend - head->ch_resbgn), PROT_NONE, 424 MAP_FIXED | MAP_PRIVATE) == MAP_FAILED)) 425 return (-1); 426 427 rtld_flags |= RT_FL_MEMRESV; 428 features |= CONF_MEMRESV; 429 } 430 } 431 432 return (features); 433 } 434 435 /* 436 * Determine whether the given file exists in the configuration file. 437 */ 438 Rtc_obj * 439 elf_config_ent(const char *name, Word hash, int id, const char **alternate) 440 { 441 Word bkt, ndx; 442 const char *str; 443 Rtc_obj *obj; 444 445 bkt = hash % config->c_hashtbl[0]; 446 ndx = config->c_hashtbl[2 + bkt]; 447 448 while (ndx) { 449 obj = config->c_objtbl + ndx; 450 str = config->c_strtbl + obj->co_name; 451 452 if ((obj->co_hash != hash) || (strcmp(name, str) != 0) || 453 (id && (id != obj->co_id))) { 454 ndx = config->c_hashchain[ndx]; 455 continue; 456 } 457 458 if ((obj->co_flags & RTC_OBJ_ALTER) && alternate) 459 *alternate = config->c_strtbl + obj->co_alter; 460 461 return (obj); 462 } 463 return (0); 464 } 465 466 /* 467 * Determine whether a filter and filtee string pair exists in the configuration 468 * file. If so, return the cached filtees that are associated with this pair as 469 * an Alist. 470 */ 471 void 472 elf_config_flt(Lm_list *lml, const char *filter, const char *string, 473 Alist **alpp, Aliste alni) 474 { 475 Rtc_fltr *fltrtbl; 476 477 for (fltrtbl = (Rtc_fltr *)config->c_fltr; fltrtbl->fr_filter; 478 fltrtbl++) { 479 Rtc_flte *fltetbl; 480 const char *fltr, *str; 481 482 fltr = config->c_strtbl + fltrtbl->fr_filter; 483 str = config->c_strtbl + fltrtbl->fr_string; 484 if (strcmp(filter, fltr) || strcmp(string, str)) 485 continue; 486 487 /* 488 * Create a path descriptor for each filtee associated with this 489 * filter/filtee string pair. Note, no expansion of filtee 490 * entries is called for, as any original expansion would have 491 * been carried out before they were recorded in the 492 * configuration file. 493 */ 494 /* LINTED */ 495 for (fltetbl = (Rtc_flte *)((char *)config->c_flte + 496 fltrtbl->fr_filtee); fltetbl->fe_filtee; fltetbl++) { 497 const char *flte; 498 Pdesc *pdp; 499 500 flte = config->c_strtbl + fltetbl->fe_filtee; 501 502 if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc), 503 alni)) == NULL) 504 return; 505 506 pdp->pd_pname = (char *)flte; 507 pdp->pd_plen = strlen(flte) + 1; 508 pdp->pd_flags = LA_SER_CONFIG; 509 510 DBG_CALL(Dbg_file_filter(lml, fltr, flte, 1)); 511 } 512 } 513 } 514