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