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 if (str = strchr(oname, ':')) { 712 size_t slen = str - oname; 713 714 (void) strncpy(buf, oname, slen); 715 buf[slen] = '\0'; 716 str = buf; 717 } else 718 str = oname; 719 720 eprintf(lml, ERR_FATAL, 721 MSG_INTL(MSG_ERR_EXPAND2), NAME(lmp), 722 str, token); 723 return (0); 724 } 725 } 726 _optr = optr; 727 } 728 729 /* 730 * First make sure the current length is shorter than PATH_MAX. We may 731 * arrive here if the given path contains '$' characters which are not 732 * the lead of a reserved token. 733 */ 734 if (nlen >= PATH_MAX) { 735 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_EXPAND1), NAME(lmp), 736 oname); 737 return (0); 738 } 739 740 /* 741 * If any ISALIST processing has occurred not only do we return the 742 * expanded node we're presently working on, but we can also update the 743 * remaining list so that it is effectively prepended with this node 744 * expanded to all remaining ISALIST options. Note that we can only 745 * handle one ISALIST per node. For more than one ISALIST to be 746 * processed we'd need a better algorithm than above to replace the 747 * newly generated list. Whether we want to encourage the number of 748 * path name permutations this would provide is another question. So, 749 * for now if more than one ISALIST is encountered we return the 750 * original node untouched. 751 */ 752 if (isa && isaflag) { 753 if (isaflag == 1) { 754 if (list) 755 *list = _list; 756 } else { 757 flags &= ~PD_TKN_ISALIST; 758 if ((nptr = (char *)stravl_insert(*name, 0, 759 (*len + 1), 1)) == NULL) 760 return (0); 761 *name = nptr; 762 return (TKN_NONE); 763 } 764 } 765 766 /* 767 * Copy any remaining string. Terminate the new string with a null as 768 * this string can be displayed via debugging diagnostics. 769 */ 770 if ((_len = (optr - _optr)) != 0) { 771 if ((nlen += _len) < PATH_MAX) { 772 (void) strncpy(nptr, _optr, _len); 773 nptr = nptr + _len; 774 } else { 775 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_ERR_EXPAND1), 776 NAME(lmp), oname); 777 return (0); 778 } 779 } 780 *nptr = '\0'; 781 782 /* 783 * A path that has been expanded is typically used to create full 784 * path names for objects that will be opened. The final path name is 785 * resolved to simplify it, and set the stage for possible $ORIGIN 786 * processing. Therefore, it's usually unnecessary to resolve the path 787 * at this point. However, if a configuration file, containing 788 * directory information is in use, then we might need to lookup this 789 * path in the configuration file. To keep the number of path name 790 * resolutions to a minimum, only resolve paths that contain "./". The 791 * use of "$ORIGIN/../lib" will probably only match a configuration file 792 * entry after resolution. 793 */ 794 if (list && (rtld_flags & RT_FL_DIRCFG) && (flags & TKN_DOTSLASH)) { 795 int len; 796 797 if ((len = resolvepath(_name, _name, (PATH_MAX - 1))) >= 0) { 798 nlen = (size_t)len; 799 _name[nlen] = '\0'; 800 flags |= PD_TKN_RESOLVED; 801 } 802 } 803 804 /* 805 * Allocate a new string if necessary. 806 * 807 * If any form of token expansion, or string resolution has occurred, 808 * the storage must be allocated for the new string. 809 * 810 * If we're processing a substring, for example, any string besides the 811 * last string within a search path "A:B:C", then this substring needs 812 * to be isolated with a null terminator. However, if this search path 813 * was created from a previous ISALIST expansion, then all strings must 814 * be allocated, as the isalist expansion will be freed after expansion 815 * processing. 816 */ 817 if ((nptr = (char *)stravl_insert(_name, 0, (nlen + 1), 1)) == NULL) 818 return (0); 819 *name = nptr; 820 *len = nlen; 821 return (flags ? flags : TKN_NONE); 822 } 823 824 /* 825 * Determine whether a path name is secure. 826 */ 827 int 828 is_path_secure(char *opath, Rt_map *clmp, uint_t info, uint_t flags) 829 { 830 Alist **salpp; 831 Aliste idx; 832 char buffer[PATH_MAX], *npath = NULL; 833 Lm_list *lml = LIST(clmp); 834 Pdesc *pdp; 835 836 /* 837 * If a path name originates from a configuration file, use it. The use 838 * of a configuration file is already validated for secure applications, 839 * so if we're using a configuration file, we must be able to use all 840 * that it defines. 841 */ 842 if (info & LA_SER_CONFIG) 843 return (1); 844 845 if ((info & LA_SER_MASK) == 0) { 846 char *str; 847 848 /* 849 * If the path name specifies a file (rather than a directory), 850 * peel off the file before making the comparison. 851 */ 852 str = strrchr(opath, '/'); 853 854 /* 855 * Carry out some initial security checks. 856 * 857 * . a simple file name (one containing no "/") is fine, as 858 * this file name will be combined with search paths to 859 * determine the complete path. Note, a secure application 860 * may provide a configuration file, and this can only be 861 * a full path name (PN_FLG_FULLPATH). 862 * . a full path (one starting with "/") is fine, provided 863 * this path name isn't a preload/audit path. 864 * . provided $ORIGIN expansion has not been employed, the 865 * above categories of path are deemed secure. 866 */ 867 if ((((str == 0) && ((info & PD_FLG_FULLPATH) == 0)) || 868 ((*opath == '/') && (str != opath) && 869 ((info & PD_FLG_EXTLOAD) == 0))) && 870 ((flags & PD_TKN_ORIGIN) == 0)) 871 return (1); 872 873 /* 874 * Determine the directory name of the present path. 875 */ 876 if (str) { 877 if (str == opath) 878 npath = (char *)MSG_ORIG(MSG_STR_SLASH); 879 else { 880 size_t size; 881 882 if ((size = str - opath) >= PATH_MAX) 883 return (0); 884 885 (void) strncpy(buffer, opath, size); 886 buffer[size] = '\0'; 887 npath = buffer; 888 } 889 890 /* 891 * If $ORIGIN processing has been employed, then allow 892 * any directory that has already been used to satisfy 893 * other dependencies, to be used. 894 */ 895 if ((flags & PD_TKN_ORIGIN) && 896 pnavl_recorded(&spavl, npath, 0, NULL)) { 897 DBG_CALL(Dbg_libs_insecure(lml, npath, 1)); 898 return (1); 899 } 900 } 901 } else { 902 /* 903 * A search path, i.e., RPATH, configuration file path, etc. is 904 * used as is. Exceptions to this are: 905 * 906 * . LD_LIBRARY_PATH. 907 * . any $ORIGIN expansion, unless used by a setuid ld.so.1 908 * to find its own dependencies, or the path name has 909 * already been used to find other dependencies. 910 * . any relative path. 911 */ 912 if (((info & LA_SER_LIBPATH) == 0) && (*opath == '/') && 913 ((flags & PD_TKN_ORIGIN) == 0)) 914 return (1); 915 916 /* 917 * If $ORIGIN processing is requested, allow a setuid ld.so.1 918 * to use this path for its own dependencies. Allow the 919 * application to use this path name only if the path name has 920 * already been used to locate other dependencies. 921 */ 922 if (flags & PD_TKN_ORIGIN) { 923 if ((lml->lm_flags & LML_FLG_RTLDLM) && 924 is_rtld_setuid()) 925 return (1); 926 else if (pnavl_recorded(&spavl, opath, 0, NULL)) { 927 DBG_CALL(Dbg_libs_insecure(lml, opath, 1)); 928 return (1); 929 } 930 } 931 npath = (char *)opath; 932 } 933 934 /* 935 * Determine whether the present directory is trusted. 936 */ 937 if (npath) { 938 salpp = LM_SECURE_DIRS(LIST(clmp)->lm_head)(); 939 for (ALIST_TRAVERSE(*salpp, idx, pdp)) { 940 if (strcmp(npath, pdp->pd_pname) == 0) 941 return (1); 942 } 943 } 944 945 /* 946 * The path is insecure, so depending on the caller, provide a 947 * diagnostic. Preloaded, or audit libraries generate a warning, as 948 * the process will run without them. 949 */ 950 if (info & PD_FLG_EXTLOAD) { 951 if (lml->lm_flags & LML_FLG_TRC_ENABLE) { 952 if ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0) 953 (void) printf(MSG_INTL(MSG_LDD_FIL_ILLEGAL), 954 opath); 955 } else 956 eprintf(lml, ERR_WARNING, MSG_INTL(MSG_SEC_ILLEGAL), 957 opath); 958 959 return (0); 960 } 961 962 /* 963 * Explicit file references are fatal. 964 */ 965 if ((info & LA_SER_MASK) == 0) { 966 if (lml->lm_flags & LML_FLG_TRC_ENABLE) { 967 /* BEGIN CSTYLED */ 968 if ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0) { 969 if (lml->lm_flags & 970 (LML_FLG_TRC_VERBOSE | LML_FLG_TRC_SEARCH)) 971 (void) printf( 972 MSG_INTL(MSG_LDD_FIL_FIND), 973 opath, NAME(clmp)); 974 975 if (((rtld_flags & RT_FL_SILENCERR) == 0) || 976 (lml->lm_flags & LML_FLG_TRC_VERBOSE)) 977 (void) printf( 978 MSG_INTL(MSG_LDD_FIL_ILLEGAL), 979 opath); 980 } 981 /* END CSTYLED */ 982 } else 983 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN), opath, 984 strerror(EACCES)); 985 } else { 986 /* 987 * Search paths. 988 */ 989 DBG_CALL(Dbg_libs_insecure(lml, opath, 0)); 990 if ((lml->lm_flags & LML_FLG_TRC_SEARCH) && 991 ((FLAGS1(clmp) & FL1_RT_LDDSTUB) == 0)) 992 (void) printf(MSG_INTL(MSG_LDD_PTH_IGNORE), opath); 993 } 994 return (0); 995 } 996 997 /* 998 * Determine whether a path already exists within the callers Pnode list. 999 */ 1000 inline static uint_t 1001 is_path_unique(Alist *alp, const char *path) 1002 { 1003 Aliste idx; 1004 Pdesc *pdp; 1005 1006 for (ALIST_TRAVERSE(alp, idx, pdp)) { 1007 if (pdp->pd_plen && (strcmp(pdp->pd_pname, path) == 0)) 1008 return (PD_FLG_DUPLICAT); 1009 } 1010 return (0); 1011 } 1012 1013 /* 1014 * Expand one or more path names. This routine is called for all path strings, 1015 * i.e., NEEDED, rpaths, default search paths, configuration file search paths, 1016 * filtees, etc. The path may be a single path name, or a colon separated list 1017 * of path names. Each individual path name is processed for possible reserved 1018 * token expansion. All string nodes are maintained in allocated memory 1019 * (regardless of whether they are constant (":"), or token expanded) to 1020 * simplify path name descriptor removal. 1021 * 1022 * The info argument passes in auxiliary information regarding the callers 1023 * intended use of the path names. This information may be maintained in the 1024 * path name descriptor element produced to describe the path name (i.e., 1025 * LA_SER_LIBPATH etc.), or may be used to determine additional security or 1026 * diagnostic processing. 1027 */ 1028 int 1029 expand_paths(Rt_map *clmp, const char *list, Alist **alpp, Aliste alni, 1030 uint_t orig, uint_t omit) 1031 { 1032 char *str, *olist = 0, *nlist = (char *)list; 1033 int fnull = FALSE; /* TRUE if empty final path segment seen */ 1034 Pdesc *pdp = NULL; 1035 1036 for (str = nlist; *nlist || fnull; str = nlist) { 1037 char *ostr; 1038 char *elist = NULL; 1039 size_t len, olen; 1040 uint_t tkns = 0; 1041 1042 if (*nlist == ';') 1043 ++nlist, ++str; 1044 if ((*nlist == ':') || fnull) { 1045 /* If not a final null segment, check following one */ 1046 fnull = !(fnull || *(nlist + 1)); 1047 1048 if (*nlist) 1049 nlist++; 1050 1051 /* 1052 * When the shell sees a null PATH segment, it 1053 * treats it as if it were the cwd (.). We mimic 1054 * this behavior for LD_LIBRARY_PATH and runpaths 1055 * (mainly for backwards compatibility with previous 1056 * behavior). For other paths, this makes no sense, 1057 * so we simply ignore the segment. 1058 */ 1059 if (!(orig & (LA_SER_LIBPATH | LA_SER_RUNPATH))) 1060 continue; /* Process next segment */ 1061 1062 str = (char *)MSG_ORIG(MSG_FMT_CWD); 1063 len = MSG_FMT_CWD_SIZE; 1064 1065 } else { 1066 uint_t _tkns; 1067 1068 len = 0; 1069 while (*nlist && (*nlist != ':') && (*nlist != ';')) { 1070 if (*nlist == '/') 1071 tkns |= PD_FLG_PNSLASH; 1072 nlist++, len++; 1073 } 1074 1075 /* Check for a following final null segment */ 1076 fnull = (*nlist == ':') && !*(nlist + 1); 1077 1078 if (*nlist) 1079 nlist++; 1080 1081 /* 1082 * Expand the captured string. Besides expanding the 1083 * present path/file entry, we may have a new list to 1084 * deal with (ISALIST expands to multiple new entries). 1085 */ 1086 elist = nlist; 1087 ostr = str; 1088 olen = len; 1089 if ((_tkns = expand(&str, &len, &elist, orig, omit, 1090 clmp)) == 0) 1091 continue; 1092 tkns |= _tkns; 1093 } 1094 1095 /* 1096 * If this a secure application, validation of the expanded 1097 * path name may be necessary. 1098 */ 1099 if ((rtld_flags & RT_FL_SECURE) && 1100 (is_path_secure(str, clmp, orig, tkns) == 0)) 1101 continue; 1102 1103 /* 1104 * If required, ensure that the string is unique. For search 1105 * paths such as LD_LIBRARY_PATH, users often inherit multiple 1106 * paths which result in unnecessary duplication. Note, if 1107 * we're debugging, any duplicate entry is retained and flagged 1108 * so that the entry can be diagnosed later as part of unused 1109 * processing. 1110 */ 1111 if (orig & PD_FLG_UNIQUE) { 1112 Word tracing; 1113 1114 tracing = LIST(clmp)->lm_flags & 1115 (LML_FLG_TRC_UNREF | LML_FLG_TRC_UNUSED); 1116 tkns |= is_path_unique(*alpp, str); 1117 1118 /* 1119 * Note, use the debug strings rpl_debug and prm_debug 1120 * as an indicator that debugging has been requested, 1121 * rather than DBG_ENABLE(), as the initial use of 1122 * LD_LIBRARY_PATH occurs in preparation for loading 1123 * our debugging library. 1124 */ 1125 if ((tkns & PD_FLG_DUPLICAT) && (tracing == 0) && 1126 (rpl_debug == 0) && (prm_debug == 0)) 1127 continue; 1128 } 1129 1130 /* 1131 * Create a new pathname descriptor. 1132 */ 1133 if ((pdp = alist_append(alpp, NULL, sizeof (Pdesc), 1134 alni)) == NULL) 1135 return (0); 1136 1137 pdp->pd_pname = str; 1138 pdp->pd_plen = len; 1139 pdp->pd_flags = (orig & LA_SER_MASK) | (tkns & PD_MSK_INHERIT); 1140 1141 /* 1142 * If token expansion occurred, maintain the original string. 1143 * This string can be used to provide a more informative error 1144 * diagnostic for a file that fails to load, or for displaying 1145 * unused search paths. 1146 */ 1147 if ((tkns & PD_MSK_EXPAND) && ((pdp->pd_oname = 1148 stravl_insert(ostr, 0, (olen + 1), 1)) == NULL)) 1149 return (0); 1150 1151 /* 1152 * Now that any duplication of the original string has occurred, 1153 * release any previous old listing. 1154 */ 1155 if (elist && (elist != nlist)) { 1156 if (olist) 1157 free(olist); 1158 nlist = olist = elist; 1159 } 1160 } 1161 1162 if (olist) 1163 free(olist); 1164 1165 /* 1166 * If no paths could be determined (perhaps because of security), then 1167 * indicate a failure. 1168 */ 1169 return (pdp != NULL); 1170 } 1171 1172 /* 1173 * Establish an objects fully resolved path. 1174 * 1175 * When $ORIGIN was first introduced, the expansion of a relative path name was 1176 * deferred until it was required. However now we insure a full path name is 1177 * always created - things like the analyzer wish to rely on librtld_db 1178 * returning a full path. The overhead of this is perceived to be low, 1179 * providing the associated libc version of getcwd is available (see 4336878). 1180 * This getcwd() was ported back to Solaris 8.1. 1181 */ 1182 size_t 1183 fullpath(Rt_map *lmp, Fdesc *fdp) 1184 { 1185 const char *name; 1186 1187 /* 1188 * Determine whether this path name is already resolved. 1189 */ 1190 if (fdp && (fdp->fd_flags & FLG_FD_RESOLVED)) { 1191 /* 1192 * If the resolved path differed from the original name, the 1193 * resolved path would have been recorded as the fd_pname. 1194 * Steal this path name from the file descriptor. Otherwise, 1195 * the path name is the same as the name of this object. 1196 */ 1197 if (fdp->fd_pname) 1198 PATHNAME(lmp) = fdp->fd_pname; 1199 else 1200 PATHNAME(lmp) = NAME(lmp); 1201 } else { 1202 /* 1203 * If this path name has not yet been resolved, resolve the 1204 * current name. 1205 */ 1206 char _path[PATH_MAX]; 1207 const char *path; 1208 int size, rsize; 1209 1210 if (fdp && fdp->fd_pname) 1211 PATHNAME(lmp) = fdp->fd_pname; 1212 else 1213 PATHNAME(lmp) = NAME(lmp); 1214 1215 name = path = PATHNAME(lmp); 1216 size = strlen(name); 1217 1218 if (path[0] != '/') { 1219 /* 1220 * If we can't determine the current directory (possible 1221 * if too many files are open - EMFILE), or if the 1222 * created path is too big, simply revert back to the 1223 * initial path name. 1224 */ 1225 if (getcwd(_path, (PATH_MAX - 2 - size)) != NULL) { 1226 (void) strcat(_path, MSG_ORIG(MSG_STR_SLASH)); 1227 (void) strcat(_path, name); 1228 path = _path; 1229 size = strlen(path); 1230 } 1231 } 1232 1233 /* 1234 * See if the path name can be reduced further. 1235 */ 1236 if ((rsize = resolvepath(path, _path, (PATH_MAX - 1))) > 0) { 1237 _path[rsize] = '\0'; 1238 path = _path; 1239 size = rsize; 1240 } 1241 1242 /* 1243 * If the path name is different from the original, duplicate it 1244 * so that it is available in a core file. If the duplication 1245 * fails simply leave the original path name alone. 1246 */ 1247 if ((PATHNAME(lmp) = 1248 stravl_insert(path, 0, (size + 1), 0)) == NULL) 1249 PATHNAME(lmp) = name; 1250 } 1251 1252 name = ORIGNAME(lmp) = PATHNAME(lmp); 1253 1254 /* 1255 * Establish the directory name size - this also acts as a flag that the 1256 * directory name has been computed. 1257 */ 1258 DIRSZ(lmp) = strrchr(name, '/') - name; 1259 return (DIRSZ(lmp)); 1260 } 1261