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