379 int
380 fpavl_insert(Lm_list *lml, Rt_map *lmp, const char *name, avl_index_t where)
381 {
382 FullPathNode *fpnp;
383 uint_t hash = sgs_str_hash(name);
384
385 if (where == 0) {
386 /* LINTED */
387 Rt_map *_lmp = fpavl_recorded(lml, name, hash, &where);
388
389 /*
390 * We better not get a hit now, we do not want duplicates in
391 * the tree.
392 */
393 ASSERT(_lmp == NULL);
394 }
395
396 /*
397 * Insert new node in tree.
398 */
399 if ((fpnp = calloc(sizeof (FullPathNode), 1)) == NULL)
400 return (0);
401
402 fpnp->fpn_node.pn_name = name;
403 fpnp->fpn_node.pn_hash = hash;
404 fpnp->fpn_lmp = lmp;
405
406 if (aplist_append(&FPNODE(lmp), fpnp, AL_CNT_FPNODE) == NULL) {
407 free(fpnp);
408 return (0);
409 }
410
411 ASSERT(lml->lm_fpavl != NULL);
412 avl_insert(lml->lm_fpavl, fpnp, where);
413 return (1);
414 }
415
416 /*
417 * Remove an object from the FullPathNode AVL tree.
418 */
419 void
442 void
443 nfavl_insert(const char *name, avl_index_t where)
444 {
445 PathNode *pnp;
446 uint_t hash = sgs_str_hash(name);
447
448 if (where == 0) {
449 /* LINTED */
450 int in_nfavl = pnavl_recorded(&nfavl, name, hash, &where);
451
452 /*
453 * We better not get a hit now, we do not want duplicates in
454 * the tree.
455 */
456 ASSERT(in_nfavl == 0);
457 }
458
459 /*
460 * Insert new node in tree.
461 */
462 if ((pnp = calloc(sizeof (PathNode), 1)) != NULL) {
463 pnp->pn_name = name;
464 pnp->pn_hash = hash;
465 avl_insert(nfavl, pnp, where);
466 }
467 }
468
469 /*
470 * Insert the directory name, of a full path name, into the secure path AVL
471 * tree.
472 *
473 * This tree is used to maintain a list of directories in which the dependencies
474 * of a secure process have been found. This list provides a fall-back in the
475 * case that a $ORIGIN expansion is deemed insecure, when the expansion results
476 * in a path name that has already provided dependencies.
477 */
478 void
479 spavl_insert(const char *name)
480 {
481 char buffer[PATH_MAX], *str;
482 size_t size;
489 */
490 if ((str = strrchr(name, '/')) == name)
491 size = 1;
492 else
493 size = str - name;
494
495 (void) strncpy(buffer, name, size);
496 buffer[size] = '\0';
497 hash = sgs_str_hash(buffer);
498
499 /*
500 * Determine whether this directory name is already recorded, or if
501 * not, 'where" will provide the insertion point for the new string.
502 */
503 if (pnavl_recorded(&spavl, buffer, hash, &where))
504 return;
505
506 /*
507 * Insert new node in tree.
508 */
509 if ((pnp = calloc(sizeof (PathNode), 1)) != NULL) {
510 pnp->pn_name = strdup(buffer);
511 pnp->pn_hash = hash;
512 avl_insert(spavl, pnp, where);
513 }
514 }
515
516 /*
517 * Inspect the generic string AVL tree for the given string. If the string is
518 * not present, duplicate it, and insert the string in the AVL tree. Return the
519 * duplicated string to the caller.
520 *
521 * These strings are maintained for the life of ld.so.1 and represent path
522 * names, file names, and search paths. All other AVL trees that maintain
523 * FullPathNode and not-found path names use the same string pointer
524 * established for this string.
525 */
526 static avl_tree_t *stravl = NULL;
527 static char *strbuf = NULL;
528 static PathNode *pnbuf = NULL;
529 static size_t strsize = 0, pnsize = 0;
2871
2872 static char errbuf[ERRSIZE], *nextptr = errbuf, *prevptr = NULL;
2873
2874 /*
2875 * All error messages go through eprintf(). During process initialization,
2876 * these messages are directed to the standard error, however once control has
2877 * been passed to the applications code these messages are stored in an internal
2878 * buffer for use with dlerror(). Note, fatal error conditions that may occur
2879 * while running the application will still cause a standard error message, see
2880 * rtldexit() in this file for details.
2881 * The RT_FL_APPLIC flag serves to indicate the transition between process
2882 * initialization and when the applications code is running.
2883 */
2884 void
2885 veprintf(Lm_list *lml, Error error, const char *format, va_list args)
2886 {
2887 int overflow = 0;
2888 static int lock = 0;
2889 Prfbuf prf;
2890
2891 if (lock || (nextptr == (errbuf + ERRSIZE)))
2892 return;
2893
2894 /*
2895 * Note: this lock is here to prevent the same thread from recursively
2896 * entering itself during a eprintf. ie: during eprintf malloc() fails
2897 * and we try and call eprintf ... and then malloc() fails ....
2898 */
2899 lock = 1;
2900
2901 /*
2902 * If we have completed startup initialization, all error messages
2903 * must be saved. These are reported through dlerror(). If we're
2904 * still in the initialization stage, output the error directly and
2905 * add a newline.
2906 */
2907 prf.pr_buf = prf.pr_cur = nextptr;
2908 prf.pr_len = ERRSIZE - (nextptr - errbuf);
2909
2910 if ((rtld_flags & RT_FL_APPLIC) == 0)
2911 prf.pr_fd = 2;
3109 /*
3110 * If the error buffer has been used, write out all
3111 * pending messages - lasterr is simply a pointer to
3112 * the last message in this buffer. However, if the
3113 * buffer couldn't be created at all, lasterr points
3114 * to a constant error message string.
3115 */
3116 if (*errbuf) {
3117 char *errptr = errbuf;
3118 char *errend = errbuf + ERRSIZE;
3119
3120 while ((errptr < errend) && *errptr) {
3121 size_t size = strlen(errptr);
3122 (void) write(2, errptr, size);
3123 (void) write(2, MSG_ORIG(MSG_STR_NL),
3124 MSG_STR_NL_SIZE);
3125 errptr += (size + 1);
3126 }
3127 }
3128 if (lasterr && ((lasterr < errbuf) ||
3129 (lasterr > (errbuf + ERRSIZE)))) {
3130 (void) write(2, lasterr, strlen(lasterr));
3131 (void) write(2, MSG_ORIG(MSG_STR_NL),
3132 MSG_STR_NL_SIZE);
3133 }
3134 }
3135 leave(lml, 0);
3136 (void) _lwp_kill(_lwp_self(), killsig);
3137 }
3138 _exit(status);
3139 }
3140
3141 /*
3142 * Map anonymous memory via MAP_ANON (added in Solaris 8).
3143 */
3144 void *
3145 dz_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
3146 {
3147 caddr_t va;
3148
3149 if ((va = (caddr_t)mmap(addr, len, prot,
|
379 int
380 fpavl_insert(Lm_list *lml, Rt_map *lmp, const char *name, avl_index_t where)
381 {
382 FullPathNode *fpnp;
383 uint_t hash = sgs_str_hash(name);
384
385 if (where == 0) {
386 /* LINTED */
387 Rt_map *_lmp = fpavl_recorded(lml, name, hash, &where);
388
389 /*
390 * We better not get a hit now, we do not want duplicates in
391 * the tree.
392 */
393 ASSERT(_lmp == NULL);
394 }
395
396 /*
397 * Insert new node in tree.
398 */
399 if ((fpnp = calloc(1, sizeof (FullPathNode))) == NULL)
400 return (0);
401
402 fpnp->fpn_node.pn_name = name;
403 fpnp->fpn_node.pn_hash = hash;
404 fpnp->fpn_lmp = lmp;
405
406 if (aplist_append(&FPNODE(lmp), fpnp, AL_CNT_FPNODE) == NULL) {
407 free(fpnp);
408 return (0);
409 }
410
411 ASSERT(lml->lm_fpavl != NULL);
412 avl_insert(lml->lm_fpavl, fpnp, where);
413 return (1);
414 }
415
416 /*
417 * Remove an object from the FullPathNode AVL tree.
418 */
419 void
442 void
443 nfavl_insert(const char *name, avl_index_t where)
444 {
445 PathNode *pnp;
446 uint_t hash = sgs_str_hash(name);
447
448 if (where == 0) {
449 /* LINTED */
450 int in_nfavl = pnavl_recorded(&nfavl, name, hash, &where);
451
452 /*
453 * We better not get a hit now, we do not want duplicates in
454 * the tree.
455 */
456 ASSERT(in_nfavl == 0);
457 }
458
459 /*
460 * Insert new node in tree.
461 */
462 if ((pnp = calloc(1, sizeof (PathNode))) != NULL) {
463 pnp->pn_name = name;
464 pnp->pn_hash = hash;
465 avl_insert(nfavl, pnp, where);
466 }
467 }
468
469 /*
470 * Insert the directory name, of a full path name, into the secure path AVL
471 * tree.
472 *
473 * This tree is used to maintain a list of directories in which the dependencies
474 * of a secure process have been found. This list provides a fall-back in the
475 * case that a $ORIGIN expansion is deemed insecure, when the expansion results
476 * in a path name that has already provided dependencies.
477 */
478 void
479 spavl_insert(const char *name)
480 {
481 char buffer[PATH_MAX], *str;
482 size_t size;
489 */
490 if ((str = strrchr(name, '/')) == name)
491 size = 1;
492 else
493 size = str - name;
494
495 (void) strncpy(buffer, name, size);
496 buffer[size] = '\0';
497 hash = sgs_str_hash(buffer);
498
499 /*
500 * Determine whether this directory name is already recorded, or if
501 * not, 'where" will provide the insertion point for the new string.
502 */
503 if (pnavl_recorded(&spavl, buffer, hash, &where))
504 return;
505
506 /*
507 * Insert new node in tree.
508 */
509 if ((pnp = calloc(1, sizeof (PathNode))) != NULL) {
510 pnp->pn_name = strdup(buffer);
511 pnp->pn_hash = hash;
512 avl_insert(spavl, pnp, where);
513 }
514 }
515
516 /*
517 * Inspect the generic string AVL tree for the given string. If the string is
518 * not present, duplicate it, and insert the string in the AVL tree. Return the
519 * duplicated string to the caller.
520 *
521 * These strings are maintained for the life of ld.so.1 and represent path
522 * names, file names, and search paths. All other AVL trees that maintain
523 * FullPathNode and not-found path names use the same string pointer
524 * established for this string.
525 */
526 static avl_tree_t *stravl = NULL;
527 static char *strbuf = NULL;
528 static PathNode *pnbuf = NULL;
529 static size_t strsize = 0, pnsize = 0;
2871
2872 static char errbuf[ERRSIZE], *nextptr = errbuf, *prevptr = NULL;
2873
2874 /*
2875 * All error messages go through eprintf(). During process initialization,
2876 * these messages are directed to the standard error, however once control has
2877 * been passed to the applications code these messages are stored in an internal
2878 * buffer for use with dlerror(). Note, fatal error conditions that may occur
2879 * while running the application will still cause a standard error message, see
2880 * rtldexit() in this file for details.
2881 * The RT_FL_APPLIC flag serves to indicate the transition between process
2882 * initialization and when the applications code is running.
2883 */
2884 void
2885 veprintf(Lm_list *lml, Error error, const char *format, va_list args)
2886 {
2887 int overflow = 0;
2888 static int lock = 0;
2889 Prfbuf prf;
2890
2891 if (lock || (nextptr > (errbuf + (ERRSIZE - 1))))
2892 return;
2893
2894 /*
2895 * Note: this lock is here to prevent the same thread from recursively
2896 * entering itself during a eprintf. ie: during eprintf malloc() fails
2897 * and we try and call eprintf ... and then malloc() fails ....
2898 */
2899 lock = 1;
2900
2901 /*
2902 * If we have completed startup initialization, all error messages
2903 * must be saved. These are reported through dlerror(). If we're
2904 * still in the initialization stage, output the error directly and
2905 * add a newline.
2906 */
2907 prf.pr_buf = prf.pr_cur = nextptr;
2908 prf.pr_len = ERRSIZE - (nextptr - errbuf);
2909
2910 if ((rtld_flags & RT_FL_APPLIC) == 0)
2911 prf.pr_fd = 2;
3109 /*
3110 * If the error buffer has been used, write out all
3111 * pending messages - lasterr is simply a pointer to
3112 * the last message in this buffer. However, if the
3113 * buffer couldn't be created at all, lasterr points
3114 * to a constant error message string.
3115 */
3116 if (*errbuf) {
3117 char *errptr = errbuf;
3118 char *errend = errbuf + ERRSIZE;
3119
3120 while ((errptr < errend) && *errptr) {
3121 size_t size = strlen(errptr);
3122 (void) write(2, errptr, size);
3123 (void) write(2, MSG_ORIG(MSG_STR_NL),
3124 MSG_STR_NL_SIZE);
3125 errptr += (size + 1);
3126 }
3127 }
3128 if (lasterr && ((lasterr < errbuf) ||
3129 (lasterr > (errbuf + (ERRSIZE - 1))))) {
3130 (void) write(2, lasterr, strlen(lasterr));
3131 (void) write(2, MSG_ORIG(MSG_STR_NL),
3132 MSG_STR_NL_SIZE);
3133 }
3134 }
3135 leave(lml, 0);
3136 (void) _lwp_kill(_lwp_self(), killsig);
3137 }
3138 _exit(status);
3139 }
3140
3141 /*
3142 * Map anonymous memory via MAP_ANON (added in Solaris 8).
3143 */
3144 void *
3145 dz_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
3146 {
3147 caddr_t va;
3148
3149 if ((va = (caddr_t)mmap(addr, len, prot,
|