Print this page
    
smatch clean rtld
    
      
        | Split | Close | 
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/sgs/rtld/common/util.c
          +++ new/usr/src/cmd/sgs/rtld/common/util.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   *      Copyright (c) 1988 AT&T
  24   24   *        All Rights Reserved
  25   25   *
  26   26   * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  27   27   */
  28   28  
  29   29  /*
  30   30   * Copyright (c) 2014 by Delphix. All rights reserved.
  31   31   */
  32   32  
  33   33  /*
  34   34   * Utility routines for run-time linker.  some are duplicated here from libc
  35   35   * (with different names) to avoid name space collisions.
  36   36   */
  37   37  #include        <sys/systeminfo.h>
  38   38  #include        <stdio.h>
  39   39  #include        <sys/time.h>
  40   40  #include        <sys/types.h>
  41   41  #include        <sys/mman.h>
  42   42  #include        <sys/lwp.h>
  43   43  #include        <sys/debug.h>
  44   44  #include        <stdarg.h>
  45   45  #include        <fcntl.h>
  46   46  #include        <string.h>
  47   47  #include        <dlfcn.h>
  48   48  #include        <unistd.h>
  49   49  #include        <stdlib.h>
  50   50  #include        <sys/auxv.h>
  51   51  #include        <limits.h>
  52   52  #include        <debug.h>
  53   53  #include        <conv.h>
  54   54  #include        "_rtld.h"
  55   55  #include        "_audit.h"
  56   56  #include        "_elf.h"
  57   57  #include        "msg.h"
  58   58  
  59   59  /*
  60   60   * Null function used as place where a debugger can set a breakpoint.
  61   61   */
  62   62  void
  63   63  rtld_db_dlactivity(Lm_list *lml)
  64   64  {
  65   65          DBG_CALL(Dbg_util_dbnotify(lml, r_debug.rtd_rdebug.r_rdevent,
  66   66              r_debug.rtd_rdebug.r_state));
  67   67  }
  68   68  
  69   69  /*
  70   70   * Null function used as place where debugger can set a pre .init
  71   71   * processing breakpoint.
  72   72   */
  73   73  void
  74   74  rtld_db_preinit(Lm_list *lml)
  75   75  {
  76   76          DBG_CALL(Dbg_util_dbnotify(lml, r_debug.rtd_rdebug.r_rdevent,
  77   77              r_debug.rtd_rdebug.r_state));
  78   78  }
  79   79  
  80   80  /*
  81   81   * Null function used as place where debugger can set a post .init
  82   82   * processing breakpoint.
  83   83   */
  84   84  void
  85   85  rtld_db_postinit(Lm_list *lml)
  86   86  {
  87   87          DBG_CALL(Dbg_util_dbnotify(lml, r_debug.rtd_rdebug.r_rdevent,
  88   88              r_debug.rtd_rdebug.r_state));
  89   89  }
  90   90  
  91   91  /*
  92   92   * Debugger Event Notification
  93   93   *
  94   94   * This function centralizes all debugger event notification (ala rtld_db).
  95   95   *
  96   96   * There's a simple intent, focused on insuring the primary link-map control
  97   97   * list (or each link-map list) is consistent, and the indication that objects
  98   98   * have been added or deleted from this list.  Although an RD_ADD and RD_DELETE
  99   99   * event are posted for each of these, most debuggers don't care, as their
 100  100   * view is that these events simply convey an "inconsistent" state.
 101  101   *
 102  102   * We also don't want to trigger multiple RD_ADD/RD_DELETE events any time we
 103  103   * enter ld.so.1.
 104  104   *
 105  105   * Set an RD_ADD/RD_DELETE event and indicate that an RD_CONSISTENT event is
 106  106   * required later (RT_FL_DBNOTIF):
 107  107   *
 108  108   *  i.  the first time we add or delete an object to the primary link-map
 109  109   *      control list.
 110  110   *  ii. the first time we move a secondary link-map control list to the primary
 111  111   *      link-map control list (effectively, this is like adding a group of
 112  112   *      objects to the primary link-map control list).
 113  113   *
 114  114   * Set an RD_CONSISTENT event when it is required (RT_FL_DBNOTIF is set):
 115  115   *
 116  116   *  i.  each time we leave the runtime linker.
 117  117   */
 118  118  void
 119  119  rd_event(Lm_list *lml, rd_event_e event, r_state_e state)
 120  120  {
 121  121          void    (*fptr)(Lm_list *);
 122  122  
 123  123          switch (event) {
 124  124          case RD_PREINIT:
 125  125                  fptr = rtld_db_preinit;
 126  126                  break;
 127  127          case RD_POSTINIT:
 128  128                  fptr = rtld_db_postinit;
 129  129                  break;
 130  130          case RD_DLACTIVITY:
 131  131                  switch (state) {
 132  132                  case RT_CONSISTENT:
 133  133                          /*
 134  134                           * Do we need to send a notification?
 135  135                           */
 136  136                          if ((rtld_flags & RT_FL_DBNOTIF) == 0)
 137  137                                  return;
 138  138                          rtld_flags &= ~RT_FL_DBNOTIF;
 139  139                          break;
 140  140                  case RT_ADD:
 141  141                  case RT_DELETE:
 142  142                          /*
 143  143                           * If we are already in an inconsistent state, no
 144  144                           * notification is required.
 145  145                           */
 146  146                          if (rtld_flags & RT_FL_DBNOTIF)
 147  147                                  return;
 148  148                          rtld_flags |= RT_FL_DBNOTIF;
 149  149                          break;
 150  150                  };
 151  151                  fptr = rtld_db_dlactivity;
 152  152                  break;
 153  153          default:
 154  154                  /*
 155  155                   * RD_NONE - do nothing
 156  156                   */
 157  157                  break;
 158  158          };
 159  159  
 160  160          /*
 161  161           * Set event state and call 'notification' function.
 162  162           *
 163  163           * The debugging clients have previously been told about these
 164  164           * notification functions and have set breakpoints on them if they
 165  165           * are interested in the notification.
 166  166           */
 167  167          r_debug.rtd_rdebug.r_state = state;
 168  168          r_debug.rtd_rdebug.r_rdevent = event;
 169  169          fptr(lml);
 170  170          r_debug.rtd_rdebug.r_rdevent = RD_NONE;
 171  171  }
 172  172  
 173  173  #if     defined(__sparc) || defined(__x86)
 174  174  /*
 175  175   * Stack Cleanup.
 176  176   *
 177  177   * This function is invoked to 'remove' arguments that were passed in on the
 178  178   * stack.  This is most likely if ld.so.1 was invoked directly.  In that case
 179  179   * we want to remove ld.so.1 as well as it's arguments from the argv[] array.
 180  180   * Which means we then need to slide everything above it on the stack down
 181  181   * accordingly.
 182  182   *
 183  183   * While the stack layout is platform specific - it just so happens that __x86,
 184  184   * and __sparc platforms share the following initial stack layout.
 185  185   *
 186  186   *      !_______________________!  high addresses
 187  187   *      !                       !
 188  188   *      !       Information     !
 189  189   *      !       Block           !
 190  190   *      !       (size varies)   !
 191  191   *      !_______________________!
 192  192   *      !       0 word          !
 193  193   *      !_______________________!
 194  194   *      !       Auxiliary       !
 195  195   *      !       vector          !
 196  196   *      !       2 word entries  !
 197  197   *      !                       !
 198  198   *      !_______________________!
 199  199   *      !       0 word          !
 200  200   *      !_______________________!
 201  201   *      !       Environment     !
 202  202   *      !       pointers        !
 203  203   *      !       ...             !
 204  204   *      !       (one word each) !
 205  205   *      !_______________________!
 206  206   *      !       0 word          !
 207  207   *      !_______________________!
 208  208   *      !       Argument        ! low addresses
 209  209   *      !       pointers        !
 210  210   *      !       Argc words      !
 211  211   *      !_______________________!
 212  212   *      !                       !
 213  213   *      !       Argc            !
 214  214   *      !_______________________!
 215  215   *      !       ...             !
 216  216   *
 217  217   */
 218  218  static void
 219  219  stack_cleanup(char **argv, char ***envp, auxv_t **auxv, int rmcnt)
 220  220  {
 221  221          int             ndx;
 222  222          long            *argc;
 223  223          char            **oargv, **nargv;
 224  224          char            **oenvp, **nenvp;
 225  225          auxv_t          *oauxv, *nauxv;
 226  226  
 227  227          /*
 228  228           * Slide ARGV[] and update argc.  The argv pointer remains the same,
 229  229           * however slide the applications arguments over the arguments to
 230  230           * ld.so.1.
 231  231           */
 232  232          nargv = &argv[0];
 233  233          oargv = &argv[rmcnt];
 234  234  
 235  235          for (ndx = 0; oargv[ndx]; ndx++)
 236  236                  nargv[ndx] = oargv[ndx];
 237  237          nargv[ndx] = oargv[ndx];
 238  238  
 239  239          argc = (long *)((uintptr_t)argv - sizeof (long *));
 240  240          *argc -= rmcnt;
 241  241  
 242  242          /*
 243  243           * Slide ENVP[], and update the environment array pointer.
 244  244           */
 245  245          ndx++;
 246  246          nenvp = &nargv[ndx];
 247  247          oenvp = &oargv[ndx];
 248  248          *envp = nenvp;
 249  249  
 250  250          for (ndx = 0; oenvp[ndx]; ndx++)
 251  251                  nenvp[ndx] = oenvp[ndx];
 252  252          nenvp[ndx] = oenvp[ndx];
 253  253  
 254  254          /*
 255  255           * Slide AUXV[], and update the aux vector pointer.
 256  256           */
 257  257          ndx++;
 258  258          nauxv = (auxv_t *)&nenvp[ndx];
 259  259          oauxv = (auxv_t *)&oenvp[ndx];
 260  260          *auxv = nauxv;
 261  261  
 262  262          for (ndx = 0; (oauxv[ndx].a_type != AT_NULL); ndx++)
 263  263                  nauxv[ndx] = oauxv[ndx];
 264  264          nauxv[ndx] = oauxv[ndx];
 265  265  }
 266  266  #else
 267  267  /*
 268  268   * Verify that the above routine is appropriate for any new platforms.
 269  269   */
 270  270  #error  unsupported architecture!
 271  271  #endif
 272  272  
 273  273  /*
 274  274   * Compare function for PathNode AVL tree.
 275  275   */
 276  276  static int
 277  277  pnavl_compare(const void *n1, const void *n2)
 278  278  {
 279  279          uint_t          hash1, hash2;
 280  280          const char      *st1, *st2;
 281  281          int             rc;
 282  282  
 283  283          hash1 = ((PathNode *)n1)->pn_hash;
 284  284          hash2 = ((PathNode *)n2)->pn_hash;
 285  285  
 286  286          if (hash1 > hash2)
 287  287                  return (1);
 288  288          if (hash1 < hash2)
 289  289                  return (-1);
 290  290  
 291  291          st1 = ((PathNode *)n1)->pn_name;
 292  292          st2 = ((PathNode *)n2)->pn_name;
 293  293  
 294  294          rc = strcmp(st1, st2);
 295  295          if (rc > 0)
 296  296                  return (1);
 297  297          if (rc < 0)
 298  298                  return (-1);
 299  299          return (0);
 300  300  }
 301  301  
 302  302  /*
 303  303   * Create an AVL tree.
 304  304   */
 305  305  static avl_tree_t *
 306  306  pnavl_create(size_t size)
 307  307  {
 308  308          avl_tree_t      *avlt;
 309  309  
 310  310          if ((avlt = malloc(sizeof (avl_tree_t))) == NULL)
 311  311                  return (NULL);
 312  312          avl_create(avlt, pnavl_compare, size, SGSOFFSETOF(PathNode, pn_avl));
 313  313          return (avlt);
 314  314  }
 315  315  
 316  316  /*
 317  317   * Determine whether a PathNode is recorded.
 318  318   */
 319  319  int
 320  320  pnavl_recorded(avl_tree_t **pnavl, const char *name, uint_t hash,
 321  321      avl_index_t *where)
 322  322  {
 323  323          PathNode        pn;
 324  324  
 325  325          /*
 326  326           * Create the avl tree if required.
 327  327           */
 328  328          if ((*pnavl == NULL) &&
 329  329              ((*pnavl = pnavl_create(sizeof (PathNode))) == NULL))
 330  330                  return (0);
 331  331  
 332  332          pn.pn_name = name;
 333  333          if ((pn.pn_hash = hash) == 0)
 334  334                  pn.pn_hash = sgs_str_hash(name);
 335  335  
 336  336          if (avl_find(*pnavl, &pn, where) == NULL)
 337  337                  return (0);
 338  338  
 339  339          return (1);
 340  340  }
 341  341  
 342  342  /*
 343  343   * Determine if a pathname has already been recorded on the full path name
 344  344   * AVL tree.  This tree maintains a node for each path name that ld.so.1 has
 345  345   * successfully loaded.  If the path name does not exist in this AVL tree, then
 346  346   * the next insertion point is deposited in "where".  This value can be used by
 347  347   * fpavl_insert() to expedite the insertion.
 348  348   */
 349  349  Rt_map *
 350  350  fpavl_recorded(Lm_list *lml, const char *name, uint_t hash, avl_index_t *where)
 351  351  {
 352  352          FullPathNode    fpn, *fpnp;
 353  353  
 354  354          /*
 355  355           * Create the avl tree if required.
 356  356           */
 357  357          if ((lml->lm_fpavl == NULL) &&
 358  358              ((lml->lm_fpavl = pnavl_create(sizeof (FullPathNode))) == NULL))
 359  359                  return (NULL);
 360  360  
 361  361          fpn.fpn_node.pn_name = name;
 362  362          if ((fpn.fpn_node.pn_hash = hash) == 0)
 363  363                  fpn.fpn_node.pn_hash = sgs_str_hash(name);
 364  364  
 365  365          if ((fpnp = avl_find(lml->lm_fpavl, &fpn, where)) == NULL)
 366  366                  return (NULL);
 367  367  
 368  368          return (fpnp->fpn_lmp);
 369  369  }
 370  370  
 371  371  /*
 372  372   * Insert a name into the FullPathNode AVL tree for the link-map list.  The
 373  373   * objects NAME() is the path that would have originally been searched for, and
 374  374   * is therefore the name to associate with any "where" value.  If the object has
 375  375   * a different PATHNAME(), perhaps because it has resolved to a different file
 376  376   * (see fullpath()), then this name will be recorded as a separate FullPathNode
 377  377   * (see load_file()).
 378  378   */
 379  379  int
 380  380  fpavl_insert(Lm_list *lml, Rt_map *lmp, const char *name, avl_index_t where)
 381  381  {
 382  382          FullPathNode    *fpnp;
 383  383          uint_t          hash = sgs_str_hash(name);
 384  384  
 385  385          if (where == 0) {
 386  386                  /* LINTED */
 387  387                  Rt_map  *_lmp = fpavl_recorded(lml, name, hash, &where);
 388  388  
  
    | ↓ open down ↓ | 388 lines elided | ↑ open up ↑ | 
 389  389                  /*
 390  390                   * We better not get a hit now, we do not want duplicates in
 391  391                   * the tree.
 392  392                   */
 393  393                  ASSERT(_lmp == NULL);
 394  394          }
 395  395  
 396  396          /*
 397  397           * Insert new node in tree.
 398  398           */
 399      -        if ((fpnp = calloc(sizeof (FullPathNode), 1)) == NULL)
      399 +        if ((fpnp = calloc(1, sizeof (FullPathNode))) == NULL)
 400  400                  return (0);
 401  401  
 402  402          fpnp->fpn_node.pn_name = name;
 403  403          fpnp->fpn_node.pn_hash = hash;
 404  404          fpnp->fpn_lmp = lmp;
 405  405  
 406  406          if (aplist_append(&FPNODE(lmp), fpnp, AL_CNT_FPNODE) == NULL) {
 407  407                  free(fpnp);
 408  408                  return (0);
 409  409          }
 410  410  
 411  411          ASSERT(lml->lm_fpavl != NULL);
 412  412          avl_insert(lml->lm_fpavl, fpnp, where);
 413  413          return (1);
 414  414  }
 415  415  
 416  416  /*
 417  417   * Remove an object from the FullPathNode AVL tree.
 418  418   */
 419  419  void
 420  420  fpavl_remove(Rt_map *lmp)
 421  421  {
 422  422          FullPathNode    *fpnp;
 423  423          Aliste          idx;
 424  424  
 425  425          for (APLIST_TRAVERSE(FPNODE(lmp), idx, fpnp)) {
 426  426                  avl_remove(LIST(lmp)->lm_fpavl, fpnp);
 427  427                  free(fpnp);
 428  428          }
 429  429          free(FPNODE(lmp));
 430  430          FPNODE(lmp) = NULL;
 431  431  }
 432  432  
 433  433  /*
 434  434   * Insert a path name into the not-found AVL tree.
 435  435   *
 436  436   * This tree maintains a node for each path name that ld.so.1 has explicitly
 437  437   * inspected, but has failed to load during a single ld.so.1 operation.  If the
 438  438   * path name does not exist in this AVL tree, then the next insertion point is
 439  439   * deposited in "where".  This value can be used by nfavl_insert() to expedite
 440  440   * the insertion.
 441  441   */
 442  442  void
 443  443  nfavl_insert(const char *name, avl_index_t where)
 444  444  {
 445  445          PathNode        *pnp;
 446  446          uint_t          hash = sgs_str_hash(name);
 447  447  
 448  448          if (where == 0) {
 449  449                  /* LINTED */
 450  450                  int     in_nfavl = pnavl_recorded(&nfavl, name, hash, &where);
 451  451  
  
    | ↓ open down ↓ | 42 lines elided | ↑ open up ↑ | 
 452  452                  /*
 453  453                   * We better not get a hit now, we do not want duplicates in
 454  454                   * the tree.
 455  455                   */
 456  456                  ASSERT(in_nfavl == 0);
 457  457          }
 458  458  
 459  459          /*
 460  460           * Insert new node in tree.
 461  461           */
 462      -        if ((pnp = calloc(sizeof (PathNode), 1)) != NULL) {
      462 +        if ((pnp = calloc(1, sizeof (PathNode))) != NULL) {
 463  463                  pnp->pn_name = name;
 464  464                  pnp->pn_hash = hash;
 465  465                  avl_insert(nfavl, pnp, where);
 466  466          }
 467  467  }
 468  468  
 469  469  /*
 470  470   * Insert the directory name, of a full path name, into the secure path AVL
 471  471   * tree.
 472  472   *
 473  473   * This tree is used to maintain a list of directories in which the dependencies
 474  474   * of a secure process have been found.  This list provides a fall-back in the
 475  475   * case that a $ORIGIN expansion is deemed insecure, when the expansion results
 476  476   * in a path name that has already provided dependencies.
 477  477   */
 478  478  void
 479  479  spavl_insert(const char *name)
 480  480  {
 481  481          char            buffer[PATH_MAX], *str;
 482  482          size_t          size;
 483  483          avl_index_t     where;
 484  484          PathNode        *pnp;
 485  485          uint_t          hash;
 486  486  
 487  487          /*
 488  488           * Separate the directory name from the path name.
 489  489           */
 490  490          if ((str = strrchr(name, '/')) == name)
 491  491                  size = 1;
 492  492          else
 493  493                  size = str - name;
 494  494  
 495  495          (void) strncpy(buffer, name, size);
 496  496          buffer[size] = '\0';
 497  497          hash = sgs_str_hash(buffer);
 498  498  
  
    | ↓ open down ↓ | 26 lines elided | ↑ open up ↑ | 
 499  499          /*
 500  500           * Determine whether this directory name is already recorded, or if
 501  501           * not, 'where" will provide the insertion point for the new string.
 502  502           */
 503  503          if (pnavl_recorded(&spavl, buffer, hash, &where))
 504  504                  return;
 505  505  
 506  506          /*
 507  507           * Insert new node in tree.
 508  508           */
 509      -        if ((pnp = calloc(sizeof (PathNode), 1)) != NULL) {
      509 +        if ((pnp = calloc(1, sizeof (PathNode))) != NULL) {
 510  510                  pnp->pn_name = strdup(buffer);
 511  511                  pnp->pn_hash = hash;
 512  512                  avl_insert(spavl, pnp, where);
 513  513          }
 514  514  }
 515  515  
 516  516  /*
 517  517   * Inspect the generic string AVL tree for the given string.  If the string is
 518  518   * not present, duplicate it, and insert the string in the AVL tree.  Return the
 519  519   * duplicated string to the caller.
 520  520   *
 521  521   * These strings are maintained for the life of ld.so.1 and represent path
 522  522   * names, file names, and search paths.  All other AVL trees that maintain
 523  523   * FullPathNode and not-found path names use the same string pointer
 524  524   * established for this string.
 525  525   */
 526  526  static avl_tree_t       *stravl = NULL;
 527  527  static char             *strbuf = NULL;
 528  528  static PathNode         *pnbuf = NULL;
 529  529  static size_t           strsize = 0, pnsize = 0;
 530  530  
 531  531  const char *
 532  532  stravl_insert(const char *name, uint_t hash, size_t nsize, int substr)
 533  533  {
 534  534          char            str[PATH_MAX];
 535  535          PathNode        *pnp;
 536  536          avl_index_t     where;
 537  537  
 538  538          /*
 539  539           * Create the avl tree if required.
 540  540           */
 541  541          if ((stravl == NULL) &&
 542  542              ((stravl = pnavl_create(sizeof (PathNode))) == NULL))
 543  543                  return (NULL);
 544  544  
 545  545          /*
 546  546           * Determine the string size if not provided by the caller.
 547  547           */
 548  548          if (nsize == 0)
 549  549                  nsize = strlen(name) + 1;
 550  550          else if (substr) {
 551  551                  /*
 552  552                   * The string passed to us may be a multiple path string for
 553  553                   * which we only need the first component.  Using the provided
 554  554                   * size, strip out the required string.
 555  555                   */
 556  556                  (void) strncpy(str, name, nsize);
 557  557                  str[nsize - 1] = '\0';
 558  558                  name = str;
 559  559          }
 560  560  
 561  561          /*
 562  562           * Allocate a PathNode buffer if one doesn't exist, or any existing
 563  563           * buffer has been used up.
 564  564           */
 565  565          if ((pnbuf == NULL) || (sizeof (PathNode) > pnsize)) {
 566  566                  pnsize = syspagsz;
 567  567                  if ((pnbuf = dz_map(0, 0, pnsize, (PROT_READ | PROT_WRITE),
 568  568                      MAP_PRIVATE)) == MAP_FAILED)
 569  569                          return (NULL);
 570  570          }
 571  571          /*
 572  572           * Determine whether this string already exists.
 573  573           */
 574  574          pnbuf->pn_name = name;
 575  575          if ((pnbuf->pn_hash = hash) == 0)
 576  576                  pnbuf->pn_hash = sgs_str_hash(name);
 577  577  
 578  578          if ((pnp = avl_find(stravl, pnbuf, &where)) != NULL)
 579  579                  return (pnp->pn_name);
 580  580  
 581  581          /*
 582  582           * Allocate a string buffer if one does not exist, or if there is
 583  583           * insufficient space for the new string in any existing buffer.
 584  584           */
 585  585          if ((strbuf == NULL) || (nsize > strsize)) {
 586  586                  strsize = S_ROUND(nsize, syspagsz);
 587  587  
 588  588                  if ((strbuf = dz_map(0, 0, strsize, (PROT_READ | PROT_WRITE),
 589  589                      MAP_PRIVATE)) == MAP_FAILED)
 590  590                          return (NULL);
 591  591          }
 592  592  
 593  593          (void) memcpy(strbuf, name, nsize);
 594  594          pnp = pnbuf;
 595  595          pnp->pn_name = strbuf;
 596  596          avl_insert(stravl, pnp, where);
 597  597  
 598  598          strbuf += nsize;
 599  599          strsize -= nsize;
 600  600          pnbuf++;
 601  601          pnsize -= sizeof (PathNode);
 602  602          return (pnp->pn_name);
 603  603  }
 604  604  
 605  605  /*
 606  606   * Prior to calling an object, either via a .plt or through dlsym(), make sure
 607  607   * its .init has fired.  Through topological sorting, ld.so.1 attempts to fire
 608  608   * init's in the correct order, however, this order is typically based on needed
 609  609   * dependencies and non-lazy relocation bindings.  Lazy relocations (.plts) can
 610  610   * still occur and result in bindings that were not captured during topological
 611  611   * sorting.  This routine compensates for this lack of binding information, and
 612  612   * provides for dynamic .init firing.
 613  613   */
 614  614  void
 615  615  is_dep_init(Rt_map *dlmp, Rt_map *clmp)
 616  616  {
 617  617          Rt_map  **tobj;
 618  618  
 619  619          /*
 620  620           * If the caller is an auditor, and the destination isn't, then don't
 621  621           * run any .inits (see comments in load_completion()).
 622  622           */
 623  623          if ((LIST(clmp)->lm_tflags & LML_TFLG_NOAUDIT) &&
 624  624              ((LIST(dlmp)->lm_tflags & LML_TFLG_NOAUDIT) == 0))
 625  625                  return;
 626  626  
 627  627          if ((dlmp == clmp) || (rtld_flags & RT_FL_INITFIRST))
 628  628                  return;
 629  629  
 630  630          (void) rt_mutex_lock(&dlmp->rt_lock);
 631  631          while (dlmp->rt_init_thread != rt_thr_self() && (FLAGS(dlmp) &
 632  632              (FLG_RT_RELOCED | FLG_RT_INITCALL | FLG_RT_INITDONE)) ==
 633  633              (FLG_RT_RELOCED | FLG_RT_INITCALL)) {
 634  634                  leave(LIST(dlmp), 0);
 635  635                  (void) _lwp_cond_wait(&dlmp->rt_cv, (mutex_t *)&dlmp->rt_lock);
 636  636                  (void) rt_mutex_unlock(&dlmp->rt_lock);
 637  637                  (void) enter(0);
 638  638                  (void) rt_mutex_lock(&dlmp->rt_lock);
 639  639          }
 640  640          (void) rt_mutex_unlock(&dlmp->rt_lock);
 641  641  
 642  642          if ((FLAGS(dlmp) & (FLG_RT_RELOCED | FLG_RT_INITDONE)) ==
 643  643              (FLG_RT_RELOCED | FLG_RT_INITDONE))
 644  644                  return;
 645  645  
 646  646          if ((tobj = calloc(2, sizeof (Rt_map *))) != NULL) {
 647  647                  tobj[0] = dlmp;
 648  648                  call_init(tobj, DBG_INIT_DYN);
 649  649          }
 650  650  }
 651  651  
 652  652  /*
 653  653   * Execute .{preinit|init|fini}array sections
 654  654   */
 655  655  void
 656  656  call_array(Addr *array, uint_t arraysz, Rt_map *lmp, Word shtype)
 657  657  {
 658  658          int     start, stop, incr, ndx;
 659  659          uint_t  arraycnt = (uint_t)(arraysz / sizeof (Addr));
 660  660  
 661  661          if (array == NULL)
 662  662                  return;
 663  663  
 664  664          /*
 665  665           * initarray & preinitarray are walked from beginning to end - while
 666  666           * finiarray is walked from end to beginning.
 667  667           */
 668  668          if (shtype == SHT_FINI_ARRAY) {
 669  669                  start = arraycnt - 1;
 670  670                  stop = incr = -1;
 671  671          } else {
 672  672                  start = 0;
 673  673                  stop = arraycnt;
 674  674                  incr = 1;
 675  675          }
 676  676  
 677  677          /*
 678  678           * Call the .*array[] entries
 679  679           */
 680  680          for (ndx = start; ndx != stop; ndx += incr) {
 681  681                  uint_t  rtldflags;
 682  682                  void    (*fptr)(void) = (void(*)())array[ndx];
 683  683  
 684  684                  DBG_CALL(Dbg_util_call_array(lmp, (void *)fptr, ndx, shtype));
 685  685  
 686  686                  APPLICATION_ENTER(rtldflags);
 687  687                  leave(LIST(lmp), 0);
 688  688                  (*fptr)();
 689  689                  (void) enter(0);
 690  690                  APPLICATION_RETURN(rtldflags);
 691  691          }
 692  692  }
 693  693  
 694  694  /*
 695  695   * Execute any .init sections.  These are passed to us in an lmp array which
 696  696   * (by default) will have been sorted.
 697  697   */
 698  698  void
 699  699  call_init(Rt_map **tobj, int flag)
 700  700  {
 701  701          Rt_map          **_tobj, **_nobj;
 702  702          static APlist   *pending = NULL;
 703  703  
 704  704          /*
 705  705           * If we're in the middle of an INITFIRST, this must complete before
 706  706           * any new init's are fired.  In this case add the object list to the
 707  707           * pending queue and return.  We'll pick up the queue after any
 708  708           * INITFIRST objects have their init's fired.
 709  709           */
 710  710          if (rtld_flags & RT_FL_INITFIRST) {
 711  711                  (void) aplist_append(&pending, tobj, AL_CNT_PENDING);
 712  712                  return;
 713  713          }
 714  714  
 715  715          /*
 716  716           * Traverse the tobj array firing each objects init.
 717  717           */
 718  718          for (_tobj = _nobj = tobj, _nobj++; *_tobj != NULL; _tobj++, _nobj++) {
 719  719                  Rt_map  *lmp = *_tobj;
 720  720                  void    (*iptr)() = INIT(lmp);
 721  721  
 722  722                  if (FLAGS(lmp) & FLG_RT_INITCALL)
 723  723                          continue;
 724  724  
 725  725                  FLAGS(lmp) |= FLG_RT_INITCALL;
 726  726                  lmp->rt_init_thread = rt_thr_self();
 727  727  
 728  728                  /*
 729  729                   * Establish an initfirst state if necessary - no other inits
 730  730                   * will be fired (because of additional relocation bindings)
 731  731                   * when in this state.
 732  732                   */
 733  733                  if (FLAGS(lmp) & FLG_RT_INITFRST)
 734  734                          rtld_flags |= RT_FL_INITFIRST;
 735  735  
 736  736                  if (INITARRAY(lmp) || iptr)
 737  737                          DBG_CALL(Dbg_util_call_init(lmp, flag));
 738  738  
 739  739                  if (iptr) {
 740  740                          uint_t  rtldflags;
 741  741  
 742  742                          APPLICATION_ENTER(rtldflags);
 743  743                          leave(LIST(lmp), 0);
 744  744                          (*iptr)();
 745  745                          (void) enter(0);
 746  746                          APPLICATION_RETURN(rtldflags);
 747  747                  }
 748  748  
 749  749                  call_array(INITARRAY(lmp), INITARRAYSZ(lmp), lmp,
 750  750                      SHT_INIT_ARRAY);
 751  751  
 752  752                  if (INITARRAY(lmp) || iptr)
 753  753                          DBG_CALL(Dbg_util_call_init(lmp, DBG_INIT_DONE));
 754  754  
 755  755                  /*
 756  756                   * Set the initdone flag regardless of whether this object
 757  757                   * actually contains an .init section.  This flag prevents us
 758  758                   * from processing this section again for an .init and also
 759  759                   * signifies that a .fini must be called should it exist.
 760  760                   * Clear the sort field for use in later .fini processing.
 761  761                   */
 762  762                  (void) rt_mutex_lock(&lmp->rt_lock);
 763  763                  FLAGS(lmp) |= FLG_RT_INITDONE;
 764  764                  lmp->rt_init_thread = (thread_t)0;
 765  765                  (void) _lwp_cond_broadcast(&lmp->rt_cv);
 766  766                  (void) rt_mutex_unlock(&lmp->rt_lock);
 767  767                  SORTVAL(lmp) = -1;
 768  768  
 769  769                  /*
 770  770                   * If we're firing an INITFIRST object, and other objects must
 771  771                   * be fired which are not INITFIRST, make sure we grab any
 772  772                   * pending objects that might have been delayed as this
 773  773                   * INITFIRST was processed.
 774  774                   */
 775  775                  if ((rtld_flags & RT_FL_INITFIRST) &&
 776  776                      ((*_nobj == NULL) || !(FLAGS(*_nobj) & FLG_RT_INITFRST))) {
 777  777                          Aliste  idx;
 778  778                          Rt_map  **pobj;
 779  779  
 780  780                          rtld_flags &= ~RT_FL_INITFIRST;
 781  781  
 782  782                          for (APLIST_TRAVERSE(pending, idx, pobj)) {
 783  783                                  aplist_delete(pending, &idx);
 784  784                                  call_init(pobj, DBG_INIT_PEND);
 785  785                          }
 786  786                  }
 787  787          }
 788  788          free(tobj);
 789  789  }
 790  790  
 791  791  /*
 792  792   * Call .fini sections for the topologically sorted list of objects.  This
 793  793   * routine is called from remove_hdl() for any objects being torn down as part
 794  794   * of a dlclose() operation, and from atexit() processing for all the remaining
 795  795   * objects within the process.
 796  796   */
 797  797  void
 798  798  call_fini(Lm_list *lml, Rt_map **tobj, Rt_map *clmp)
 799  799  {
 800  800          Rt_map **_tobj;
 801  801  
 802  802          for (_tobj = tobj; *_tobj != NULL; _tobj++) {
 803  803                  Rt_map          *lmp = *_tobj;
 804  804  
 805  805                  /*
 806  806                   * Only fire a .fini if the objects corresponding .init has
 807  807                   * completed.  We collect all .fini sections of objects that
 808  808                   * had their .init collected, but that doesn't mean that at
 809  809                   * the time of collection, that the .init had completed.
 810  810                   */
 811  811                  if (FLAGS(lmp) & FLG_RT_INITDONE) {
 812  812                          void    (*fptr)(void) = FINI(lmp);
 813  813  
 814  814                          if (FINIARRAY(lmp) || fptr)
 815  815                                  DBG_CALL(Dbg_util_call_fini(lmp));
 816  816  
 817  817                          call_array(FINIARRAY(lmp), FINIARRAYSZ(lmp), lmp,
 818  818                              SHT_FINI_ARRAY);
 819  819  
 820  820                          if (fptr) {
 821  821                                  uint_t  rtldflags;
 822  822  
 823  823                                  APPLICATION_ENTER(rtldflags);
 824  824                                  leave(lml, 0);
 825  825                                  (*fptr)();
 826  826                                  (void) enter(0);
 827  827                                  APPLICATION_RETURN(rtldflags);
 828  828                          }
 829  829                  }
 830  830  
 831  831                  /*
 832  832                   * Skip main, this is explicitly called last in atexit_fini().
 833  833                   */
 834  834                  if (FLAGS(lmp) & FLG_RT_ISMAIN)
 835  835                          continue;
 836  836  
 837  837                  /*
 838  838                   * This object has exercised its last instructions (regardless
 839  839                   * of whether it will be unmapped or not).  Audit this closure.
 840  840                   */
 841  841                  if ((lml->lm_tflags & LML_TFLG_NOAUDIT) == 0)
 842  842                          audit_objclose(lmp, clmp);
 843  843          }
 844  844  
 845  845          DBG_CALL(Dbg_bind_plt_summary(lml, M_MACH, pltcnt21d, pltcnt24d,
 846  846              pltcntu32, pltcntu44, pltcntfull, pltcntfar));
 847  847  
 848  848          free(tobj);
 849  849  }
 850  850  
 851  851  /*
 852  852   * Function called by atexit(3C).  Calls all .fini sections within the objects
 853  853   * that make up the process.  As .fini processing is the last opportunity for
 854  854   * any new bindings to be established, this is also a convenient location to
 855  855   * check for unused objects.
 856  856   */
 857  857  void
 858  858  atexit_fini()
 859  859  {
 860  860          Rt_map  **tobj, *lmp;
 861  861          Lm_list *lml;
 862  862          Aliste  idx;
 863  863  
 864  864          (void) enter(0);
 865  865  
 866  866          rtld_flags |= RT_FL_ATEXIT;
 867  867  
 868  868          lml = &lml_main;
 869  869          lml->lm_flags |= LML_FLG_ATEXIT;
 870  870          lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 871  871          lmp = (Rt_map *)lml->lm_head;
 872  872  
 873  873          /*
 874  874           * Reverse topologically sort the main link-map for .fini execution.
 875  875           */
 876  876          if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 877  877              (tobj != (Rt_map **)S_ERROR))
 878  878                  call_fini(lml, tobj, NULL);
 879  879  
 880  880          /*
 881  881           * Now that all .fini code has been run, see what unreferenced objects
 882  882           * remain.
 883  883           */
 884  884          unused(lml);
 885  885  
 886  886          /*
 887  887           * Traverse any alternative link-map lists, looking for non-auditors.
 888  888           */
 889  889          for (APLIST_TRAVERSE(dynlm_list, idx, lml)) {
 890  890                  /*
 891  891                   * Ignore the base-link-map list, which has already been
 892  892                   * processed, the runtime linkers link-map list, which is
 893  893                   * processed last, and any auditors.
 894  894                   */
 895  895                  if ((lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM)) ||
 896  896                      (lml->lm_tflags & LML_TFLG_AUD_MASK) ||
 897  897                      ((lmp = (Rt_map *)lml->lm_head) == NULL))
 898  898                          continue;
 899  899  
 900  900                  lml->lm_flags |= LML_FLG_ATEXIT;
 901  901                  lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 902  902  
 903  903                  /*
 904  904                   * Reverse topologically sort the link-map for .fini execution.
 905  905                   */
 906  906                  if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 907  907                      (tobj != (Rt_map **)S_ERROR))
 908  908                          call_fini(lml, tobj, NULL);
 909  909  
 910  910                  unused(lml);
 911  911          }
 912  912  
 913  913          /*
 914  914           * Add an explicit close to main and ld.so.1.  Although main's .fini is
 915  915           * collected in call_fini() to provide for FINITARRAY processing, its
 916  916           * audit_objclose is explicitly skipped.  This provides for it to be
 917  917           * called last, here.  This is the reverse of the explicit calls to
 918  918           * audit_objopen() made in setup().
 919  919           */
 920  920          lml = &lml_main;
 921  921          lmp = (Rt_map *)lml->lm_head;
 922  922  
 923  923          if ((lml->lm_tflags | AFLAGS(lmp)) & LML_TFLG_AUD_MASK) {
 924  924                  audit_objclose((Rt_map *)lml_rtld.lm_head, lmp);
 925  925                  audit_objclose(lmp, lmp);
 926  926          }
 927  927  
 928  928          /*
 929  929           * Traverse any alternative link-map lists, looking for non-auditors.
 930  930           */
 931  931          for (APLIST_TRAVERSE(dynlm_list, idx, lml)) {
 932  932                  /*
 933  933                   * Ignore the base-link-map list, which has already been
 934  934                   * processed, the runtime linkers link-map list, which is
 935  935                   * processed last, and any non-auditors.
 936  936                   */
 937  937                  if ((lml->lm_flags & (LML_FLG_BASELM | LML_FLG_RTLDLM)) ||
 938  938                      ((lml->lm_tflags & LML_TFLG_AUD_MASK) == 0) ||
 939  939                      ((lmp = (Rt_map *)lml->lm_head) == NULL))
 940  940                          continue;
 941  941  
 942  942                  lml->lm_flags |= LML_FLG_ATEXIT;
 943  943                  lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 944  944  
 945  945                  /*
 946  946                   * Reverse topologically sort the link-map for .fini execution.
 947  947                   */
 948  948                  if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 949  949                      (tobj != (Rt_map **)S_ERROR))
 950  950                          call_fini(lml, tobj, NULL);
 951  951  
 952  952                  unused(lml);
 953  953          }
 954  954  
 955  955          /*
 956  956           * Finally reverse topologically sort the runtime linkers link-map for
 957  957           * .fini execution.
 958  958           */
 959  959          lml = &lml_rtld;
 960  960          lml->lm_flags |= LML_FLG_ATEXIT;
 961  961          lml->lm_flags &= ~LML_FLG_INTRPOSETSORT;
 962  962          lmp = (Rt_map *)lml->lm_head;
 963  963  
 964  964          if (((tobj = tsort(lmp, lml->lm_obj, RT_SORT_FWD)) != NULL) &&
 965  965              (tobj != (Rt_map **)S_ERROR))
 966  966                  call_fini(lml, tobj, NULL);
 967  967  
 968  968          leave(&lml_main, 0);
 969  969  }
 970  970  
 971  971  /*
 972  972   * This routine is called to complete any runtime linker activity which may have
 973  973   * resulted in objects being loaded.  This is called from all user entry points
 974  974   * and from any internal dl*() requests.
 975  975   */
 976  976  void
 977  977  load_completion(Rt_map *nlmp)
 978  978  {
 979  979          Rt_map  **tobj = NULL;
 980  980          Lm_list *nlml;
 981  981  
 982  982          /*
 983  983           * Establish any .init processing.  Note, in a world of lazy loading,
 984  984           * objects may have been loaded regardless of whether the users request
 985  985           * was fulfilled (i.e., a dlsym() request may have failed to find a
 986  986           * symbol but objects might have been loaded during its search).  Thus,
 987  987           * any tsorting starts from the nlmp (new link-maps) pointer and not
 988  988           * necessarily from the link-map that may have satisfied the request.
 989  989           *
 990  990           * Note, the primary link-map has an initialization phase where dynamic
 991  991           * .init firing is suppressed.  This provides for a simple and clean
 992  992           * handshake with the primary link-maps libc, which is important for
 993  993           * establishing uberdata.  In addition, auditors often obtain handles
 994  994           * to primary link-map objects as the objects are loaded, so as to
 995  995           * inspect the link-map for symbols.  This inspection is allowed without
 996  996           * running any code on the primary link-map, as running this code may
 997  997           * reenter the auditor, who may not yet have finished its own
 998  998           * initialization.
 999  999           */
1000 1000          if (nlmp)
1001 1001                  nlml = LIST(nlmp);
1002 1002  
1003 1003          if (nlmp && nlml->lm_init && ((nlml != &lml_main) ||
1004 1004              (rtld_flags2 & (RT_FL2_PLMSETUP | RT_FL2_NOPLM)))) {
1005 1005                  if ((tobj = tsort(nlmp, nlml->lm_init,
1006 1006                      RT_SORT_REV)) == (Rt_map **)S_ERROR)
1007 1007                          tobj = NULL;
1008 1008          }
1009 1009  
1010 1010          /*
1011 1011           * Make sure any alternative link-map retrieves any external interfaces
1012 1012           * and initializes threads.
1013 1013           */
1014 1014          if (nlmp && (nlml != &lml_main)) {
1015 1015                  (void) rt_get_extern(nlml, nlmp);
1016 1016                  rt_thr_init(nlml);
1017 1017          }
1018 1018  
1019 1019          /*
1020 1020           * Traverse the list of new link-maps and register any dynamic TLS.
1021 1021           * This storage is established for any objects not on the primary
1022 1022           * link-map, and for any objects added to the primary link-map after
1023 1023           * static TLS has been registered.
1024 1024           */
1025 1025          if (nlmp && nlml->lm_tls && ((nlml != &lml_main) ||
1026 1026              (rtld_flags2 & (RT_FL2_PLMSETUP | RT_FL2_NOPLM)))) {
1027 1027                  Rt_map  *lmp;
1028 1028  
1029 1029                  for (lmp = nlmp; lmp; lmp = NEXT_RT_MAP(lmp)) {
1030 1030                          if (PTTLS(lmp) && PTTLS(lmp)->p_memsz)
1031 1031                                  tls_modaddrem(lmp, TM_FLG_MODADD);
1032 1032                  }
1033 1033                  nlml->lm_tls = 0;
1034 1034          }
1035 1035  
1036 1036          /*
1037 1037           * Fire any .init's.
1038 1038           */
1039 1039          if (tobj)
1040 1040                  call_init(tobj, DBG_INIT_SORT);
1041 1041  }
1042 1042  
1043 1043  /*
1044 1044   * Append an item to the specified link map control list.
1045 1045   */
1046 1046  void
1047 1047  lm_append(Lm_list *lml, Aliste lmco, Rt_map *lmp)
1048 1048  {
1049 1049          Lm_cntl *lmc;
1050 1050          int     add = 1;
1051 1051  
1052 1052          /*
1053 1053           * Indicate that this link-map list has a new object.
1054 1054           */
1055 1055          (lml->lm_obj)++;
1056 1056  
1057 1057          /*
1058 1058           * If we're about to add a new object to the main link-map control
1059 1059           * list, alert the debuggers.  Additions of individual objects to the
1060 1060           * main link-map control list occur during initial setup as the
1061 1061           * applications immediate dependencies are loaded.  Additional objects
1062 1062           * are loaded on the main link-map control list after they have been
1063 1063           * fully initialized on an alternative link-map control list.  See
1064 1064           * lm_move().
1065 1065           */
1066 1066          if (lmco == ALIST_OFF_DATA)
1067 1067                  rd_event(lml, RD_DLACTIVITY, RT_ADD);
1068 1068  
1069 1069          /* LINTED */
1070 1070          lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, lmco);
1071 1071  
1072 1072          /*
1073 1073           * A link-map list header points to one of more link-map control lists
1074 1074           * (see include/rtld.h).  The initial list, pointed to by lm_cntl, is
1075 1075           * the list of relocated objects.  Other lists maintain objects that
1076 1076           * are still being analyzed or relocated.  This list provides the core
1077 1077           * link-map list information used by all ld.so.1 routines.
1078 1078           */
1079 1079          if (lmc->lc_head == NULL) {
1080 1080                  /*
1081 1081                   * If this is the first link-map for the given control list,
1082 1082                   * initialize the list.
1083 1083                   */
1084 1084                  lmc->lc_head = lmc->lc_tail = lmp;
1085 1085                  add = 0;
1086 1086  
1087 1087          } else if (FLAGS(lmp) & FLG_RT_OBJINTPO) {
1088 1088                  Rt_map  *tlmp;
1089 1089  
1090 1090                  /*
1091 1091                   * If this is an interposer then append the link-map following
1092 1092                   * any other interposers (these are objects that have been
1093 1093                   * previously preloaded, or were identified with -z interpose).
1094 1094                   * Interposers can only be inserted on the first link-map
1095 1095                   * control list, as once relocation has started, interposition
1096 1096                   * from new interposers can't be guaranteed.
1097 1097                   *
1098 1098                   * NOTE: We do not interpose on the head of a list.  This model
1099 1099                   * evolved because dynamic executables have already been fully
1100 1100                   * relocated within themselves and thus can't be interposed on.
1101 1101                   * Nowadays it's possible to have shared objects at the head of
1102 1102                   * a list, which conceptually means they could be interposed on.
1103 1103                   * But, shared objects can be created via dldump() and may only
1104 1104                   * be partially relocated (just relatives), in which case they
1105 1105                   * are interposable, but are marked as fixed (ET_EXEC).
1106 1106                   *
1107 1107                   * Thus we really don't have a clear method of deciding when the
1108 1108                   * head of a link-map is interposable.  So, to be consistent,
1109 1109                   * for now only add interposers after the link-map lists head
1110 1110                   * object.
1111 1111                   */
1112 1112                  for (tlmp = NEXT_RT_MAP(lmc->lc_head); tlmp;
1113 1113                      tlmp = NEXT_RT_MAP(tlmp)) {
1114 1114  
1115 1115                          if (FLAGS(tlmp) & FLG_RT_OBJINTPO)
1116 1116                                  continue;
1117 1117  
1118 1118                          /*
1119 1119                           * Insert the new link-map before this non-interposer,
1120 1120                           * and indicate an interposer is found.
1121 1121                           */
1122 1122                          NEXT(PREV_RT_MAP(tlmp)) = (Link_map *)lmp;
1123 1123                          PREV(lmp) = PREV(tlmp);
1124 1124  
1125 1125                          NEXT(lmp) = (Link_map *)tlmp;
1126 1126                          PREV(tlmp) = (Link_map *)lmp;
1127 1127  
1128 1128                          lmc->lc_flags |= LMC_FLG_REANALYZE;
1129 1129                          add = 0;
1130 1130                          break;
1131 1131                  }
1132 1132          }
1133 1133  
1134 1134          /*
1135 1135           * Fall through to appending the new link map to the tail of the list.
1136 1136           * If we're processing the initial objects of this link-map list, add
1137 1137           * them to the backward compatibility list.
1138 1138           */
1139 1139          if (add) {
1140 1140                  NEXT(lmc->lc_tail) = (Link_map *)lmp;
1141 1141                  PREV(lmp) = (Link_map *)lmc->lc_tail;
1142 1142                  lmc->lc_tail = lmp;
1143 1143          }
1144 1144  
1145 1145          /*
1146 1146           * Having added this link-map to a control list, indicate which control
1147 1147           * list the link-map belongs to.  Note, control list information is
1148 1148           * always maintained as an offset, as the Alist can be reallocated.
1149 1149           */
1150 1150          CNTL(lmp) = lmco;
1151 1151  
1152 1152          /*
1153 1153           * Indicate if an interposer is found.  Note that the first object on a
1154 1154           * link-map can be explicitly defined as an interposer so that it can
1155 1155           * provide interposition over direct binding requests.
1156 1156           */
1157 1157          if (FLAGS(lmp) & MSK_RT_INTPOSE)
1158 1158                  lml->lm_flags |= LML_FLG_INTRPOSE;
1159 1159  
1160 1160          /*
1161 1161           * For backward compatibility with debuggers, the link-map list contains
1162 1162           * pointers to the main control list.
1163 1163           */
1164 1164          if (lmco == ALIST_OFF_DATA) {
1165 1165                  lml->lm_head = lmc->lc_head;
1166 1166                  lml->lm_tail = lmc->lc_tail;
1167 1167          }
1168 1168  }
1169 1169  
1170 1170  /*
1171 1171   * Delete an item from the specified link map control list.
1172 1172   */
1173 1173  void
1174 1174  lm_delete(Lm_list *lml, Rt_map *lmp, Rt_map *clmp)
1175 1175  {
1176 1176          Lm_cntl *lmc;
1177 1177  
1178 1178          /*
1179 1179           * If the control list pointer hasn't been initialized, this object
1180 1180           * never got added to a link-map list.
1181 1181           */
1182 1182          if (CNTL(lmp) == 0)
1183 1183                  return;
1184 1184  
1185 1185          /*
1186 1186           * If we're about to delete an object from the main link-map control
1187 1187           * list, alert the debuggers.
1188 1188           */
1189 1189          if (CNTL(lmp) == ALIST_OFF_DATA)
1190 1190                  rd_event(lml, RD_DLACTIVITY, RT_DELETE);
1191 1191  
1192 1192          /*
1193 1193           * If we're being audited tell the audit library that we're
1194 1194           * about to go deleting dependencies.
1195 1195           */
1196 1196          if (clmp && (aud_activity ||
1197 1197              ((LIST(clmp)->lm_tflags | AFLAGS(clmp)) & LML_TFLG_AUD_ACTIVITY)))
1198 1198                  audit_activity(clmp, LA_ACT_DELETE);
1199 1199  
1200 1200          /* LINTED */
1201 1201          lmc = (Lm_cntl *)alist_item_by_offset(lml->lm_lists, CNTL(lmp));
1202 1202  
1203 1203          if (lmc->lc_head == lmp)
1204 1204                  lmc->lc_head = NEXT_RT_MAP(lmp);
1205 1205          else
1206 1206                  NEXT(PREV_RT_MAP(lmp)) = (void *)NEXT(lmp);
1207 1207  
1208 1208          if (lmc->lc_tail == lmp)
1209 1209                  lmc->lc_tail = PREV_RT_MAP(lmp);
1210 1210          else
1211 1211                  PREV(NEXT_RT_MAP(lmp)) = PREV(lmp);
1212 1212  
1213 1213          /*
1214 1214           * For backward compatibility with debuggers, the link-map list contains
1215 1215           * pointers to the main control list.
1216 1216           */
1217 1217          if (lmc == (Lm_cntl *)&lml->lm_lists->al_data) {
1218 1218                  lml->lm_head = lmc->lc_head;
1219 1219                  lml->lm_tail = lmc->lc_tail;
1220 1220          }
1221 1221  
1222 1222          /*
1223 1223           * Indicate we have one less object on this control list.
1224 1224           */
1225 1225          (lml->lm_obj)--;
1226 1226  }
1227 1227  
1228 1228  /*
1229 1229   * Move a link-map control list to another.  Objects that are being relocated
1230 1230   * are maintained on secondary control lists.  Once their relocation is
1231 1231   * complete, the entire list is appended to the previous control list, as this
1232 1232   * list must have been the trigger for generating the new control list.
1233 1233   */
1234 1234  void
1235 1235  lm_move(Lm_list *lml, Aliste nlmco, Aliste plmco, Lm_cntl *nlmc, Lm_cntl *plmc)
1236 1236  {
1237 1237          Rt_map  *lmp;
1238 1238  
1239 1239          /*
1240 1240           * If we're about to add a new family of objects to the main link-map
1241 1241           * control list, alert the debuggers.  Additions of object families to
1242 1242           * the main link-map control list occur during lazy loading, filtering
1243 1243           * and dlopen().
1244 1244           */
1245 1245          if (plmco == ALIST_OFF_DATA)
1246 1246                  rd_event(lml, RD_DLACTIVITY, RT_ADD);
1247 1247  
1248 1248          DBG_CALL(Dbg_file_cntl(lml, nlmco, plmco));
1249 1249  
1250 1250          /*
1251 1251           * Indicate each new link-map has been moved to the previous link-map
1252 1252           * control list.
1253 1253           */
1254 1254          for (lmp = nlmc->lc_head; lmp; lmp = NEXT_RT_MAP(lmp)) {
1255 1255                  CNTL(lmp) = plmco;
1256 1256  
1257 1257                  /*
1258 1258                   * If these objects are being added to the main link-map
1259 1259                   * control list, indicate that there are init's available
1260 1260                   * for harvesting.
1261 1261                   */
1262 1262                  if (plmco == ALIST_OFF_DATA) {
1263 1263                          lml->lm_init++;
1264 1264                          lml->lm_flags |= LML_FLG_OBJADDED;
1265 1265                  }
1266 1266          }
1267 1267  
1268 1268          /*
1269 1269           * Move the new link-map control list, to the callers link-map control
1270 1270           * list.
1271 1271           */
1272 1272          if (plmc->lc_head == NULL) {
1273 1273                  plmc->lc_head = nlmc->lc_head;
1274 1274                  PREV(nlmc->lc_head) = NULL;
1275 1275          } else {
1276 1276                  NEXT(plmc->lc_tail) = (Link_map *)nlmc->lc_head;
1277 1277                  PREV(nlmc->lc_head) = (Link_map *)plmc->lc_tail;
1278 1278          }
1279 1279  
1280 1280          plmc->lc_tail = nlmc->lc_tail;
1281 1281          nlmc->lc_head = nlmc->lc_tail = NULL;
1282 1282  
1283 1283          /*
1284 1284           * For backward compatibility with debuggers, the link-map list contains
1285 1285           * pointers to the main control list.
1286 1286           */
1287 1287          if (plmco == ALIST_OFF_DATA) {
1288 1288                  lml->lm_head = plmc->lc_head;
1289 1289                  lml->lm_tail = plmc->lc_tail;
1290 1290          }
1291 1291  }
1292 1292  
1293 1293  /*
1294 1294   * Create, or assign a link-map control list.  Each link-map list contains a
1295 1295   * main control list, which has an Alist offset of ALIST_OFF_DATA (see the
1296 1296   * description in include/rtld.h).  During the initial construction of a
1297 1297   * process, objects are added to this main control list.  This control list is
1298 1298   * never deleted, unless an alternate link-map list has been requested (say for
1299 1299   * auditors), and the associated objects could not be loaded or relocated.
1300 1300   *
1301 1301   * Once relocation has started, any lazy loadable objects, or filtees, are
1302 1302   * processed on a new, temporary control list.  Only when these objects have
1303 1303   * been fully relocated, are they moved to the main link-map control list.
1304 1304   * Once the objects are moved, this temporary control list is deleted (see
1305 1305   * remove_cntl()).
1306 1306   *
1307 1307   * A dlopen() always requires a new temporary link-map control list.
1308 1308   * Typically, a dlopen() occurs on a link-map list that had already started
1309 1309   * relocation, however, auditors can dlopen() objects on the main link-map
1310 1310   * list while under initial construction, before any relocation has begun.
1311 1311   * Hence, dlopen() requests are explicitly flagged.
1312 1312   */
1313 1313  Aliste
1314 1314  create_cntl(Lm_list *lml, int dlopen)
1315 1315  {
1316 1316          /*
1317 1317           * If the head link-map object has already been relocated, create a
1318 1318           * new, temporary, control list.
1319 1319           */
1320 1320          if (dlopen || (lml->lm_head == NULL) ||
1321 1321              (FLAGS(lml->lm_head) & FLG_RT_RELOCED)) {
1322 1322                  Lm_cntl *lmc;
1323 1323  
1324 1324                  if ((lmc = alist_append(&lml->lm_lists, NULL, sizeof (Lm_cntl),
1325 1325                      AL_CNT_LMLISTS)) == NULL)
1326 1326                          return (NULL);
1327 1327  
1328 1328                  return ((Aliste)((char *)lmc - (char *)lml->lm_lists));
1329 1329          }
1330 1330  
1331 1331          return (ALIST_OFF_DATA);
1332 1332  }
1333 1333  
1334 1334  /*
1335 1335   * Environment variables can have a variety of defined permutations, and thus
1336 1336   * the following infrastructure exists to allow this variety and to select the
1337 1337   * required definition.
1338 1338   *
1339 1339   * Environment variables can be defined as 32- or 64-bit specific, and if so
1340 1340   * they will take precedence over any instruction set neutral form.  Typically
1341 1341   * this is only useful when the environment value is an informational string.
1342 1342   *
1343 1343   * Environment variables may be obtained from the standard user environment or
1344 1344   * from a configuration file.  The latter provides a fallback if no user
1345 1345   * environment setting is found, and can take two forms:
1346 1346   *
1347 1347   *  -   a replaceable definition - this will be used if no user environment
1348 1348   *      setting has been seen, or
1349 1349   *
1350 1350   *  -   an permanent definition - this will be used no matter what user
1351 1351   *      environment setting is seen.  In the case of list variables it will be
1352 1352   *      appended to any process environment setting seen.
1353 1353   *
1354 1354   * Environment variables can be defined without a value (ie. LD_XXXX=) so as to
1355 1355   * override any replaceable environment variables from a configuration file.
1356 1356   */
1357 1357  static  u_longlong_t            rplgen = 0;     /* replaceable generic */
1358 1358                                                  /*      variables */
1359 1359  static  u_longlong_t            rplisa = 0;     /* replaceable ISA specific */
1360 1360                                                  /*      variables */
1361 1361  static  u_longlong_t            prmgen = 0;     /* permanent generic */
1362 1362                                                  /*      variables */
1363 1363  static  u_longlong_t            prmisa = 0;     /* permanent ISA specific */
1364 1364                                                  /*      variables */
1365 1365  static  u_longlong_t            cmdgen = 0;     /* command line (-e) generic */
1366 1366                                                  /*      variables */
1367 1367  static  u_longlong_t            cmdisa = 0;     /* command line (-e) ISA */
1368 1368                                                  /*      specific variables */
1369 1369  
1370 1370  /*
1371 1371   * Classify an environment variables type.
1372 1372   */
1373 1373  #define ENV_TYP_IGNORE          0x01            /* ignore - variable is for */
1374 1374                                                  /*      the wrong ISA */
1375 1375  #define ENV_TYP_ISA             0x02            /* variable is ISA specific */
1376 1376  #define ENV_TYP_CONFIG          0x04            /* variable obtained from a */
1377 1377                                                  /*      config file */
1378 1378  #define ENV_TYP_PERMANT         0x08            /* variable is permanent */
1379 1379  #define ENV_TYP_CMDLINE         0x10            /* variable provide with -e */
1380 1380  #define ENV_TYP_NULL            0x20            /* variable is null */
1381 1381  
1382 1382  /*
1383 1383   * Identify all environment variables.
1384 1384   */
1385 1385  #define ENV_FLG_AUDIT           0x0000000000001ULL
1386 1386  #define ENV_FLG_AUDIT_ARGS      0x0000000000002ULL
1387 1387  #define ENV_FLG_BIND_NOW        0x0000000000004ULL
1388 1388  #define ENV_FLG_BIND_NOT        0x0000000000008ULL
1389 1389  #define ENV_FLG_BINDINGS        0x0000000000010ULL
1390 1390  #define ENV_FLG_CONFGEN         0x0000000000020ULL
1391 1391  #define ENV_FLG_CONFIG          0x0000000000040ULL
1392 1392  #define ENV_FLG_DEBUG           0x0000000000080ULL
1393 1393  #define ENV_FLG_DEBUG_OUTPUT    0x0000000000100ULL
1394 1394  #define ENV_FLG_DEMANGLE        0x0000000000200ULL
1395 1395  #define ENV_FLG_FLAGS           0x0000000000400ULL
1396 1396  #define ENV_FLG_INIT            0x0000000000800ULL
1397 1397  #define ENV_FLG_LIBPATH         0x0000000001000ULL
1398 1398  #define ENV_FLG_LOADAVAIL       0x0000000002000ULL
1399 1399  #define ENV_FLG_LOADFLTR        0x0000000004000ULL
1400 1400  #define ENV_FLG_NOAUDIT         0x0000000008000ULL
1401 1401  #define ENV_FLG_NOAUXFLTR       0x0000000010000ULL
1402 1402  #define ENV_FLG_NOBAPLT         0x0000000020000ULL
1403 1403  #define ENV_FLG_NOCONFIG        0x0000000040000ULL
1404 1404  #define ENV_FLG_NODIRCONFIG     0x0000000080000ULL
1405 1405  #define ENV_FLG_NODIRECT        0x0000000100000ULL
1406 1406  #define ENV_FLG_NOENVCONFIG     0x0000000200000ULL
1407 1407  #define ENV_FLG_NOLAZY          0x0000000400000ULL
1408 1408  #define ENV_FLG_NOOBJALTER      0x0000000800000ULL
1409 1409  #define ENV_FLG_NOVERSION       0x0000001000000ULL
1410 1410  #define ENV_FLG_PRELOAD         0x0000002000000ULL
1411 1411  #define ENV_FLG_PROFILE         0x0000004000000ULL
1412 1412  #define ENV_FLG_PROFILE_OUTPUT  0x0000008000000ULL
1413 1413  #define ENV_FLG_SIGNAL          0x0000010000000ULL
1414 1414  #define ENV_FLG_TRACE_OBJS      0x0000020000000ULL
1415 1415  #define ENV_FLG_TRACE_PTHS      0x0000040000000ULL
1416 1416  #define ENV_FLG_UNREF           0x0000080000000ULL
1417 1417  #define ENV_FLG_UNUSED          0x0000100000000ULL
1418 1418  #define ENV_FLG_VERBOSE         0x0000200000000ULL
1419 1419  #define ENV_FLG_WARN            0x0000400000000ULL
1420 1420  #define ENV_FLG_NOFLTCONFIG     0x0000800000000ULL
1421 1421  #define ENV_FLG_BIND_LAZY       0x0001000000000ULL
1422 1422  #define ENV_FLG_NOUNRESWEAK     0x0002000000000ULL
1423 1423  #define ENV_FLG_NOPAREXT        0x0004000000000ULL
1424 1424  #define ENV_FLG_HWCAP           0x0008000000000ULL
1425 1425  #define ENV_FLG_SFCAP           0x0010000000000ULL
1426 1426  #define ENV_FLG_MACHCAP         0x0020000000000ULL
1427 1427  #define ENV_FLG_PLATCAP         0x0040000000000ULL
1428 1428  #define ENV_FLG_CAP_FILES       0x0080000000000ULL
1429 1429  #define ENV_FLG_DEFERRED        0x0100000000000ULL
1430 1430  #define ENV_FLG_NOENVIRON       0x0200000000000ULL
1431 1431  
1432 1432  #define SEL_REPLACE             0x0001
1433 1433  #define SEL_PERMANT             0x0002
1434 1434  #define SEL_ACT_RT              0x0100  /* setting rtld_flags */
1435 1435  #define SEL_ACT_RT2             0x0200  /* setting rtld_flags2 */
1436 1436  #define SEL_ACT_STR             0x0400  /* setting string value */
1437 1437  #define SEL_ACT_LML             0x0800  /* setting lml_flags */
1438 1438  #define SEL_ACT_LMLT            0x1000  /* setting lml_tflags */
1439 1439  #define SEL_ACT_SPEC_1          0x2000  /* for FLG_{FLAGS, LIBPATH} */
1440 1440  #define SEL_ACT_SPEC_2          0x4000  /* need special handling */
1441 1441  
1442 1442  /*
1443 1443   * Pattern match an LD_XXXX environment variable.  s1 points to the XXXX part
1444 1444   * and len specifies its length (comparing a strings length before the string
1445 1445   * itself speed things up).  s2 points to the token itself which has already
1446 1446   * had any leading white-space removed.
1447 1447   */
1448 1448  static void
1449 1449  ld_generic_env(const char *s1, size_t len, const char *s2, Word *lmflags,
1450 1450      Word *lmtflags, uint_t env_flags, int aout)
1451 1451  {
1452 1452          u_longlong_t    variable = 0;
1453 1453          ushort_t        select = 0;
1454 1454          const char      **str;
1455 1455          Word            val = 0;
1456 1456  
1457 1457          /*
1458 1458           * Determine whether we're dealing with a replaceable or permanent
1459 1459           * string.
1460 1460           */
1461 1461          if (env_flags & ENV_TYP_PERMANT) {
1462 1462                  /*
1463 1463                   * If the string is from a configuration file and defined as
1464 1464                   * permanent, assign it as permanent.
1465 1465                   */
1466 1466                  select |= SEL_PERMANT;
1467 1467          } else
1468 1468                  select |= SEL_REPLACE;
1469 1469  
1470 1470          /*
1471 1471           * Parse the variable given.
1472 1472           *
1473 1473           * The LD_AUDIT family.
1474 1474           */
1475 1475          if (*s1 == 'A') {
1476 1476                  if ((len == MSG_LD_AUDIT_SIZE) && (strncmp(s1,
1477 1477                      MSG_ORIG(MSG_LD_AUDIT), MSG_LD_AUDIT_SIZE) == 0)) {
1478 1478                          /*
1479 1479                           * Replaceable and permanent audit objects can exist.
1480 1480                           */
1481 1481                          select |= SEL_ACT_STR;
1482 1482                          str = (select & SEL_REPLACE) ? &rpl_audit : &prm_audit;
1483 1483                          variable = ENV_FLG_AUDIT;
1484 1484                  } else if ((len == MSG_LD_AUDIT_ARGS_SIZE) &&
1485 1485                      (strncmp(s1, MSG_ORIG(MSG_LD_AUDIT_ARGS),
1486 1486                      MSG_LD_AUDIT_ARGS_SIZE) == 0)) {
1487 1487                          /*
1488 1488                           * A specialized variable for plt_exit() use, not
1489 1489                           * documented for general use.
1490 1490                           */
1491 1491                          select |= SEL_ACT_SPEC_2;
1492 1492                          variable = ENV_FLG_AUDIT_ARGS;
1493 1493                  }
1494 1494          }
1495 1495          /*
1496 1496           * The LD_BIND family.
1497 1497           */
1498 1498          else if (*s1 == 'B') {
1499 1499                  if ((len == MSG_LD_BIND_LAZY_SIZE) && (strncmp(s1,
1500 1500                      MSG_ORIG(MSG_LD_BIND_LAZY),
1501 1501                      MSG_LD_BIND_LAZY_SIZE) == 0)) {
1502 1502                          select |= SEL_ACT_RT2;
1503 1503                          val = RT_FL2_BINDLAZY;
1504 1504                          variable = ENV_FLG_BIND_LAZY;
1505 1505                  } else if ((len == MSG_LD_BIND_NOW_SIZE) && (strncmp(s1,
1506 1506                      MSG_ORIG(MSG_LD_BIND_NOW), MSG_LD_BIND_NOW_SIZE) == 0)) {
1507 1507                          select |= SEL_ACT_RT2;
1508 1508                          val = RT_FL2_BINDNOW;
1509 1509                          variable = ENV_FLG_BIND_NOW;
1510 1510                  } else if ((len == MSG_LD_BIND_NOT_SIZE) && (strncmp(s1,
1511 1511                      MSG_ORIG(MSG_LD_BIND_NOT), MSG_LD_BIND_NOT_SIZE) == 0)) {
1512 1512                          /*
1513 1513                           * Another trick, enabled to help debug AOUT
1514 1514                           * applications under BCP, but not documented for
1515 1515                           * general use.
1516 1516                           */
1517 1517                          select |= SEL_ACT_RT;
1518 1518                          val = RT_FL_NOBIND;
1519 1519                          variable = ENV_FLG_BIND_NOT;
1520 1520                  } else if ((len == MSG_LD_BINDINGS_SIZE) && (strncmp(s1,
1521 1521                      MSG_ORIG(MSG_LD_BINDINGS), MSG_LD_BINDINGS_SIZE) == 0)) {
1522 1522                          /*
1523 1523                           * This variable is simply for backward compatibility.
1524 1524                           * If this and LD_DEBUG are both specified, only one of
1525 1525                           * the strings is going to get processed.
1526 1526                           */
1527 1527                          select |= SEL_ACT_SPEC_2;
1528 1528                          variable = ENV_FLG_BINDINGS;
1529 1529                  }
1530 1530          }
1531 1531          /*
1532 1532           * LD_CAP_FILES and LD_CONFIG family.
1533 1533           */
1534 1534          else if (*s1 == 'C') {
1535 1535                  if ((len == MSG_LD_CAP_FILES_SIZE) && (strncmp(s1,
1536 1536                      MSG_ORIG(MSG_LD_CAP_FILES), MSG_LD_CAP_FILES_SIZE) == 0)) {
1537 1537                          select |= SEL_ACT_STR;
1538 1538                          str = (select & SEL_REPLACE) ?
1539 1539                              &rpl_cap_files : &prm_cap_files;
1540 1540                          variable = ENV_FLG_CAP_FILES;
1541 1541                  } else if ((len == MSG_LD_CONFGEN_SIZE) && (strncmp(s1,
1542 1542                      MSG_ORIG(MSG_LD_CONFGEN), MSG_LD_CONFGEN_SIZE) == 0)) {
1543 1543                          /*
1544 1544                           * This variable is not documented for general use.
1545 1545                           * Although originaly designed for internal use with
1546 1546                           * crle(1), this variable is in use by the Studio
1547 1547                           * auditing tools.  Hence, it can't be removed.
1548 1548                           */
1549 1549                          select |= SEL_ACT_SPEC_2;
1550 1550                          variable = ENV_FLG_CONFGEN;
1551 1551                  } else if ((len == MSG_LD_CONFIG_SIZE) && (strncmp(s1,
1552 1552                      MSG_ORIG(MSG_LD_CONFIG), MSG_LD_CONFIG_SIZE) == 0)) {
1553 1553                          /*
1554 1554                           * Secure applications must use a default configuration
1555 1555                           * file.  A setting from a configuration file doesn't
1556 1556                           * make sense (given we must be reading a configuration
1557 1557                           * file to have gotten this).
1558 1558                           */
1559 1559                          if ((rtld_flags & RT_FL_SECURE) ||
1560 1560                              (env_flags & ENV_TYP_CONFIG))
1561 1561                                  return;
1562 1562                          select |= SEL_ACT_STR;
1563 1563                          str = &config->c_name;
1564 1564                          variable = ENV_FLG_CONFIG;
1565 1565                  }
1566 1566          }
1567 1567          /*
1568 1568           * The LD_DEBUG family, LD_DEFERRED (internal, used by ldd(1)), and
1569 1569           * LD_DEMANGLE.
1570 1570           */
1571 1571          else if (*s1 == 'D') {
1572 1572                  if ((len == MSG_LD_DEBUG_SIZE) && (strncmp(s1,
1573 1573                      MSG_ORIG(MSG_LD_DEBUG), MSG_LD_DEBUG_SIZE) == 0)) {
1574 1574                          select |= SEL_ACT_STR;
1575 1575                          str = (select & SEL_REPLACE) ? &rpl_debug : &prm_debug;
1576 1576                          variable = ENV_FLG_DEBUG;
1577 1577                  } else if ((len == MSG_LD_DEBUG_OUTPUT_SIZE) && (strncmp(s1,
1578 1578                      MSG_ORIG(MSG_LD_DEBUG_OUTPUT),
1579 1579                      MSG_LD_DEBUG_OUTPUT_SIZE) == 0)) {
1580 1580                          select |= SEL_ACT_STR;
1581 1581                          str = &dbg_file;
1582 1582                          variable = ENV_FLG_DEBUG_OUTPUT;
1583 1583                  } else if ((len == MSG_LD_DEFERRED_SIZE) && (strncmp(s1,
1584 1584                      MSG_ORIG(MSG_LD_DEFERRED), MSG_LD_DEFERRED_SIZE) == 0)) {
1585 1585                          select |= SEL_ACT_RT;
1586 1586                          val = RT_FL_DEFERRED;
1587 1587                          variable = ENV_FLG_DEFERRED;
1588 1588                  } else if ((len == MSG_LD_DEMANGLE_SIZE) && (strncmp(s1,
1589 1589                      MSG_ORIG(MSG_LD_DEMANGLE), MSG_LD_DEMANGLE_SIZE) == 0)) {
1590 1590                          select |= SEL_ACT_RT;
1591 1591                          val = RT_FL_DEMANGLE;
1592 1592                          variable = ENV_FLG_DEMANGLE;
1593 1593                  }
1594 1594          }
1595 1595          /*
1596 1596           * LD_FLAGS - collect the best variable definition.  On completion of
1597 1597           * environment variable processing pass the result to ld_flags_env()
1598 1598           * where they'll be decomposed and passed back to this routine.
1599 1599           */
1600 1600          else if (*s1 == 'F') {
1601 1601                  if ((len == MSG_LD_FLAGS_SIZE) && (strncmp(s1,
1602 1602                      MSG_ORIG(MSG_LD_FLAGS), MSG_LD_FLAGS_SIZE) == 0)) {
1603 1603                          select |= SEL_ACT_SPEC_1;
1604 1604                          str = (select & SEL_REPLACE) ? &rpl_ldflags :
1605 1605                              &prm_ldflags;
1606 1606                          variable = ENV_FLG_FLAGS;
1607 1607                  }
1608 1608          }
1609 1609          /*
1610 1610           * LD_HWCAP.
1611 1611           */
1612 1612          else if (*s1 == 'H') {
1613 1613                  if ((len == MSG_LD_HWCAP_SIZE) && (strncmp(s1,
1614 1614                      MSG_ORIG(MSG_LD_HWCAP), MSG_LD_HWCAP_SIZE) == 0)) {
1615 1615                          select |= SEL_ACT_STR;
1616 1616                          str = (select & SEL_REPLACE) ?
1617 1617                              &rpl_hwcap : &prm_hwcap;
1618 1618                          variable = ENV_FLG_HWCAP;
1619 1619                  }
1620 1620          }
1621 1621          /*
1622 1622           * LD_INIT (internal, used by ldd(1)).
1623 1623           */
1624 1624          else if (*s1 == 'I') {
1625 1625                  if ((len == MSG_LD_INIT_SIZE) && (strncmp(s1,
1626 1626                      MSG_ORIG(MSG_LD_INIT), MSG_LD_INIT_SIZE) == 0)) {
1627 1627                          select |= SEL_ACT_LML;
1628 1628                          val = LML_FLG_TRC_INIT;
1629 1629                          variable = ENV_FLG_INIT;
1630 1630                  }
1631 1631          }
1632 1632          /*
1633 1633           * The LD_LIBRARY_PATH and LD_LOAD families.
1634 1634           */
1635 1635          else if (*s1 == 'L') {
1636 1636                  if ((len == MSG_LD_LIBPATH_SIZE) && (strncmp(s1,
1637 1637                      MSG_ORIG(MSG_LD_LIBPATH), MSG_LD_LIBPATH_SIZE) == 0)) {
1638 1638                          select |= SEL_ACT_SPEC_1;
1639 1639                          str = (select & SEL_REPLACE) ? &rpl_libpath :
1640 1640                              &prm_libpath;
1641 1641                          variable = ENV_FLG_LIBPATH;
1642 1642                  } else if ((len == MSG_LD_LOADAVAIL_SIZE) && (strncmp(s1,
1643 1643                      MSG_ORIG(MSG_LD_LOADAVAIL), MSG_LD_LOADAVAIL_SIZE) == 0)) {
1644 1644                          /*
1645 1645                           * This variable is not documented for general use.
1646 1646                           * Although originaly designed for internal use with
1647 1647                           * crle(1), this variable is in use by the Studio
1648 1648                           * auditing tools.  Hence, it can't be removed.
1649 1649                           */
1650 1650                          select |= SEL_ACT_LML;
1651 1651                          val = LML_FLG_LOADAVAIL;
1652 1652                          variable = ENV_FLG_LOADAVAIL;
1653 1653                  } else if ((len == MSG_LD_LOADFLTR_SIZE) && (strncmp(s1,
1654 1654                      MSG_ORIG(MSG_LD_LOADFLTR), MSG_LD_LOADFLTR_SIZE) == 0)) {
1655 1655                          select |= SEL_ACT_SPEC_2;
1656 1656                          variable = ENV_FLG_LOADFLTR;
1657 1657                  }
1658 1658          }
1659 1659          /*
1660 1660           * LD_MACHCAP.
1661 1661           */
1662 1662          else if (*s1 == 'M') {
1663 1663                  if ((len == MSG_LD_MACHCAP_SIZE) && (strncmp(s1,
1664 1664                      MSG_ORIG(MSG_LD_MACHCAP), MSG_LD_MACHCAP_SIZE) == 0)) {
1665 1665                          select |= SEL_ACT_STR;
1666 1666                          str = (select & SEL_REPLACE) ?
1667 1667                              &rpl_machcap : &prm_machcap;
1668 1668                          variable = ENV_FLG_MACHCAP;
1669 1669                  }
1670 1670          }
1671 1671          /*
1672 1672           * The LD_NO family.
1673 1673           */
1674 1674          else if (*s1 == 'N') {
1675 1675                  if ((len == MSG_LD_NOAUDIT_SIZE) && (strncmp(s1,
1676 1676                      MSG_ORIG(MSG_LD_NOAUDIT), MSG_LD_NOAUDIT_SIZE) == 0)) {
1677 1677                          select |= SEL_ACT_RT;
1678 1678                          val = RT_FL_NOAUDIT;
1679 1679                          variable = ENV_FLG_NOAUDIT;
1680 1680                  } else if ((len == MSG_LD_NOAUXFLTR_SIZE) && (strncmp(s1,
1681 1681                      MSG_ORIG(MSG_LD_NOAUXFLTR), MSG_LD_NOAUXFLTR_SIZE) == 0)) {
1682 1682                          select |= SEL_ACT_RT;
1683 1683                          val = RT_FL_NOAUXFLTR;
1684 1684                          variable = ENV_FLG_NOAUXFLTR;
1685 1685                  } else if ((len == MSG_LD_NOBAPLT_SIZE) && (strncmp(s1,
1686 1686                      MSG_ORIG(MSG_LD_NOBAPLT), MSG_LD_NOBAPLT_SIZE) == 0)) {
1687 1687                          select |= SEL_ACT_RT;
1688 1688                          val = RT_FL_NOBAPLT;
1689 1689                          variable = ENV_FLG_NOBAPLT;
1690 1690                  } else if ((len == MSG_LD_NOCONFIG_SIZE) && (strncmp(s1,
1691 1691                      MSG_ORIG(MSG_LD_NOCONFIG), MSG_LD_NOCONFIG_SIZE) == 0)) {
1692 1692                          select |= SEL_ACT_RT;
1693 1693                          val = RT_FL_NOCFG;
1694 1694                          variable = ENV_FLG_NOCONFIG;
1695 1695                  } else if ((len == MSG_LD_NODIRCONFIG_SIZE) && (strncmp(s1,
1696 1696                      MSG_ORIG(MSG_LD_NODIRCONFIG),
1697 1697                      MSG_LD_NODIRCONFIG_SIZE) == 0)) {
1698 1698                          select |= SEL_ACT_RT;
1699 1699                          val = RT_FL_NODIRCFG;
1700 1700                          variable = ENV_FLG_NODIRCONFIG;
1701 1701                  } else if ((len == MSG_LD_NODIRECT_SIZE) && (strncmp(s1,
1702 1702                      MSG_ORIG(MSG_LD_NODIRECT), MSG_LD_NODIRECT_SIZE) == 0)) {
1703 1703                          select |= SEL_ACT_LMLT;
1704 1704                          val = LML_TFLG_NODIRECT;
1705 1705                          variable = ENV_FLG_NODIRECT;
1706 1706                  } else if ((len == MSG_LD_NOENVCONFIG_SIZE) && (strncmp(s1,
1707 1707                      MSG_ORIG(MSG_LD_NOENVCONFIG),
1708 1708                      MSG_LD_NOENVCONFIG_SIZE) == 0)) {
1709 1709                          select |= SEL_ACT_RT;
1710 1710                          val = RT_FL_NOENVCFG;
1711 1711                          variable = ENV_FLG_NOENVCONFIG;
1712 1712                  } else if ((len == MSG_LD_NOFLTCONFIG_SIZE) && (strncmp(s1,
1713 1713                      MSG_ORIG(MSG_LD_NOFLTCONFIG),
1714 1714                      MSG_LD_NOFLTCONFIG_SIZE) == 0)) {
1715 1715                          select |= SEL_ACT_RT2;
1716 1716                          val = RT_FL2_NOFLTCFG;
1717 1717                          variable = ENV_FLG_NOFLTCONFIG;
1718 1718                  } else if ((len == MSG_LD_NOLAZY_SIZE) && (strncmp(s1,
1719 1719                      MSG_ORIG(MSG_LD_NOLAZY), MSG_LD_NOLAZY_SIZE) == 0)) {
1720 1720                          select |= SEL_ACT_LMLT;
1721 1721                          val = LML_TFLG_NOLAZYLD;
1722 1722                          variable = ENV_FLG_NOLAZY;
1723 1723                  } else if ((len == MSG_LD_NOOBJALTER_SIZE) && (strncmp(s1,
1724 1724                      MSG_ORIG(MSG_LD_NOOBJALTER),
1725 1725                      MSG_LD_NOOBJALTER_SIZE) == 0)) {
1726 1726                          select |= SEL_ACT_RT;
1727 1727                          val = RT_FL_NOOBJALT;
1728 1728                          variable = ENV_FLG_NOOBJALTER;
1729 1729                  } else if ((len == MSG_LD_NOVERSION_SIZE) && (strncmp(s1,
1730 1730                      MSG_ORIG(MSG_LD_NOVERSION), MSG_LD_NOVERSION_SIZE) == 0)) {
1731 1731                          select |= SEL_ACT_RT;
1732 1732                          val = RT_FL_NOVERSION;
1733 1733                          variable = ENV_FLG_NOVERSION;
1734 1734                  } else if ((len == MSG_LD_NOUNRESWEAK_SIZE) && (strncmp(s1,
1735 1735                      MSG_ORIG(MSG_LD_NOUNRESWEAK),
1736 1736                      MSG_LD_NOUNRESWEAK_SIZE) == 0)) {
1737 1737                          /*
1738 1738                           * LD_NOUNRESWEAK (internal, used by ldd(1)).
1739 1739                           */
1740 1740                          select |= SEL_ACT_LML;
1741 1741                          val = LML_FLG_TRC_NOUNRESWEAK;
1742 1742                          variable = ENV_FLG_NOUNRESWEAK;
1743 1743                  } else if ((len == MSG_LD_NOPAREXT_SIZE) && (strncmp(s1,
1744 1744                      MSG_ORIG(MSG_LD_NOPAREXT), MSG_LD_NOPAREXT_SIZE) == 0)) {
1745 1745                          select |= SEL_ACT_LML;
1746 1746                          val = LML_FLG_TRC_NOPAREXT;
1747 1747                          variable = ENV_FLG_NOPAREXT;
1748 1748                  } else if ((len == MSG_LD_NOENVIRON_SIZE) && (strncmp(s1,
1749 1749                      MSG_ORIG(MSG_LD_NOENVIRON), MSG_LD_NOENVIRON_SIZE) == 0)) {
1750 1750                          /*
1751 1751                           * LD_NOENVIRON can only be set with ld.so.1 -e.
1752 1752                           */
1753 1753                          select |= SEL_ACT_RT;
1754 1754                          val = RT_FL_NOENVIRON;
1755 1755                          variable = ENV_FLG_NOENVIRON;
1756 1756                  }
1757 1757          }
1758 1758          /*
1759 1759           * LD_PLATCAP, LD_PRELOAD and LD_PROFILE family.
1760 1760           */
1761 1761          else if (*s1 == 'P') {
1762 1762                  if ((len == MSG_LD_PLATCAP_SIZE) && (strncmp(s1,
1763 1763                      MSG_ORIG(MSG_LD_PLATCAP), MSG_LD_PLATCAP_SIZE) == 0)) {
1764 1764                          select |= SEL_ACT_STR;
1765 1765                          str = (select & SEL_REPLACE) ?
1766 1766                              &rpl_platcap : &prm_platcap;
1767 1767                          variable = ENV_FLG_PLATCAP;
1768 1768                  } else if ((len == MSG_LD_PRELOAD_SIZE) && (strncmp(s1,
1769 1769                      MSG_ORIG(MSG_LD_PRELOAD), MSG_LD_PRELOAD_SIZE) == 0)) {
1770 1770                          select |= SEL_ACT_STR;
1771 1771                          str = (select & SEL_REPLACE) ? &rpl_preload :
1772 1772                              &prm_preload;
1773 1773                          variable = ENV_FLG_PRELOAD;
1774 1774                  } else if ((len == MSG_LD_PROFILE_SIZE) && (strncmp(s1,
1775 1775                      MSG_ORIG(MSG_LD_PROFILE), MSG_LD_PROFILE_SIZE) == 0)) {
1776 1776                          /*
1777 1777                           * Only one user library can be profiled at a time.
1778 1778                           */
1779 1779                          select |= SEL_ACT_SPEC_2;
1780 1780                          variable = ENV_FLG_PROFILE;
1781 1781                  } else if ((len == MSG_LD_PROFILE_OUTPUT_SIZE) && (strncmp(s1,
1782 1782                      MSG_ORIG(MSG_LD_PROFILE_OUTPUT),
1783 1783                      MSG_LD_PROFILE_OUTPUT_SIZE) == 0)) {
1784 1784                          /*
1785 1785                           * Only one user library can be profiled at a time.
1786 1786                           */
1787 1787                          select |= SEL_ACT_STR;
1788 1788                          str = &profile_out;
1789 1789                          variable = ENV_FLG_PROFILE_OUTPUT;
1790 1790                  }
1791 1791          }
1792 1792          /*
1793 1793           * LD_SFCAP and LD_SIGNAL.
1794 1794           */
1795 1795          else if (*s1 == 'S') {
1796 1796                  if ((len == MSG_LD_SFCAP_SIZE) && (strncmp(s1,
1797 1797                      MSG_ORIG(MSG_LD_SFCAP), MSG_LD_SFCAP_SIZE) == 0)) {
1798 1798                          select |= SEL_ACT_STR;
1799 1799                          str = (select & SEL_REPLACE) ?
1800 1800                              &rpl_sfcap : &prm_sfcap;
1801 1801                          variable = ENV_FLG_SFCAP;
1802 1802                  } else if ((len == MSG_LD_SIGNAL_SIZE) &&
1803 1803                      (strncmp(s1, MSG_ORIG(MSG_LD_SIGNAL),
1804 1804                      MSG_LD_SIGNAL_SIZE) == 0) &&
1805 1805                      ((rtld_flags & RT_FL_SECURE) == 0)) {
1806 1806                          select |= SEL_ACT_SPEC_2;
1807 1807                          variable = ENV_FLG_SIGNAL;
1808 1808                  }
1809 1809          }
1810 1810          /*
1811 1811           * The LD_TRACE family (internal, used by ldd(1)).  This definition is
1812 1812           * the key to enabling all other ldd(1) specific environment variables.
1813 1813           * In case an auditor is called, which in turn might exec(2) a
1814 1814           * subprocess, this variable is disabled, so that any subprocess
1815 1815           * escapes ldd(1) processing.
1816 1816           */
1817 1817          else if (*s1 == 'T') {
1818 1818                  if (((len == MSG_LD_TRACE_OBJS_SIZE) &&
1819 1819                      (strncmp(s1, MSG_ORIG(MSG_LD_TRACE_OBJS),
1820 1820                      MSG_LD_TRACE_OBJS_SIZE) == 0)) ||
1821 1821                      ((len == MSG_LD_TRACE_OBJS_E_SIZE) &&
1822 1822                      (((strncmp(s1, MSG_ORIG(MSG_LD_TRACE_OBJS_E),
1823 1823                      MSG_LD_TRACE_OBJS_E_SIZE) == 0) && !aout) ||
1824 1824                      ((strncmp(s1, MSG_ORIG(MSG_LD_TRACE_OBJS_A),
1825 1825                      MSG_LD_TRACE_OBJS_A_SIZE) == 0) && aout)))) {
1826 1826                          char    *s0 = (char *)s1;
1827 1827  
1828 1828                          select |= SEL_ACT_SPEC_2;
1829 1829                          variable = ENV_FLG_TRACE_OBJS;
1830 1830  
1831 1831  #if     defined(__sparc) || defined(__x86)
1832 1832                          /*
1833 1833                           * The simplest way to "disable" this variable is to
1834 1834                           * truncate this string to "LD_'\0'". This string is
1835 1835                           * ignored by any ld.so.1 environment processing.
1836 1836                           * Use of such interfaces as unsetenv(3c) are overkill,
1837 1837                           * and would drag too much libc implementation detail
1838 1838                           * into ld.so.1.
1839 1839                           */
1840 1840                          *s0 = '\0';
1841 1841  #else
1842 1842  /*
1843 1843   * Verify that the above write is appropriate for any new platforms.
1844 1844   */
1845 1845  #error  unsupported architecture!
1846 1846  #endif
1847 1847                  } else if ((len == MSG_LD_TRACE_PTHS_SIZE) && (strncmp(s1,
1848 1848                      MSG_ORIG(MSG_LD_TRACE_PTHS),
1849 1849                      MSG_LD_TRACE_PTHS_SIZE) == 0)) {
1850 1850                          select |= SEL_ACT_LML;
1851 1851                          val = LML_FLG_TRC_SEARCH;
1852 1852                          variable = ENV_FLG_TRACE_PTHS;
1853 1853                  }
1854 1854          }
1855 1855          /*
1856 1856           * LD_UNREF and LD_UNUSED (internal, used by ldd(1)).
1857 1857           */
1858 1858          else if (*s1 == 'U') {
1859 1859                  if ((len == MSG_LD_UNREF_SIZE) && (strncmp(s1,
1860 1860                      MSG_ORIG(MSG_LD_UNREF), MSG_LD_UNREF_SIZE) == 0)) {
1861 1861                          select |= SEL_ACT_LML;
1862 1862                          val = LML_FLG_TRC_UNREF;
1863 1863                          variable = ENV_FLG_UNREF;
1864 1864                  } else if ((len == MSG_LD_UNUSED_SIZE) && (strncmp(s1,
1865 1865                      MSG_ORIG(MSG_LD_UNUSED), MSG_LD_UNUSED_SIZE) == 0)) {
1866 1866                          select |= SEL_ACT_LML;
1867 1867                          val = LML_FLG_TRC_UNUSED;
1868 1868                          variable = ENV_FLG_UNUSED;
1869 1869                  }
1870 1870          }
1871 1871          /*
1872 1872           * LD_VERBOSE (internal, used by ldd(1)).
1873 1873           */
1874 1874          else if (*s1 == 'V') {
1875 1875                  if ((len == MSG_LD_VERBOSE_SIZE) && (strncmp(s1,
1876 1876                      MSG_ORIG(MSG_LD_VERBOSE), MSG_LD_VERBOSE_SIZE) == 0)) {
1877 1877                          select |= SEL_ACT_LML;
1878 1878                          val = LML_FLG_TRC_VERBOSE;
1879 1879                          variable = ENV_FLG_VERBOSE;
1880 1880                  }
1881 1881          }
1882 1882          /*
1883 1883           * LD_WARN (internal, used by ldd(1)).
1884 1884           */
1885 1885          else if (*s1 == 'W') {
1886 1886                  if ((len == MSG_LD_WARN_SIZE) && (strncmp(s1,
1887 1887                      MSG_ORIG(MSG_LD_WARN), MSG_LD_WARN_SIZE) == 0)) {
1888 1888                          select |= SEL_ACT_LML;
1889 1889                          val = LML_FLG_TRC_WARN;
1890 1890                          variable = ENV_FLG_WARN;
1891 1891                  }
1892 1892          }
1893 1893  
1894 1894          if (variable == 0)
1895 1895                  return;
1896 1896  
1897 1897          /*
1898 1898           * If the variable is already processed with and ISA specific variable,
1899 1899           * no further processing is needed.
1900 1900           */
1901 1901          if (((select & SEL_REPLACE) && (rplisa & variable)) ||
1902 1902              ((select & SEL_PERMANT) && (prmisa & variable)))
1903 1903                  return;
1904 1904  
1905 1905          /*
1906 1906           * If this variable has already been set via the command line, then
1907 1907           * ignore this variable.  The command line, -e, takes precedence.
1908 1908           */
1909 1909          if (env_flags & ENV_TYP_ISA) {
1910 1910                  if (cmdisa & variable)
1911 1911                          return;
1912 1912                  if (env_flags & ENV_TYP_CMDLINE)
1913 1913                          cmdisa |= variable;
1914 1914          } else {
1915 1915                  if (cmdgen & variable)
1916 1916                          return;
1917 1917                  if (env_flags & ENV_TYP_CMDLINE)
1918 1918                          cmdgen |= variable;
1919 1919          }
1920 1920  
1921 1921          /*
1922 1922           * Mark the appropriate variables.
1923 1923           */
1924 1924          if (env_flags & ENV_TYP_ISA) {
1925 1925                  /*
1926 1926                   * This is an ISA setting.
1927 1927                   */
1928 1928                  if (select & SEL_REPLACE) {
1929 1929                          if (rplisa & variable)
1930 1930                                  return;
1931 1931                          rplisa |= variable;
1932 1932                  } else {
1933 1933                          prmisa |= variable;
1934 1934                  }
1935 1935          } else {
1936 1936                  /*
1937 1937                   * This is a non-ISA setting.
1938 1938                   */
1939 1939                  if (select & SEL_REPLACE) {
1940 1940                          if (rplgen & variable)
1941 1941                                  return;
1942 1942                          rplgen |= variable;
1943 1943                  } else
1944 1944                          prmgen |= variable;
1945 1945          }
1946 1946  
1947 1947          /*
1948 1948           * Now perform the setting.
1949 1949           */
1950 1950          if (select & SEL_ACT_RT) {
1951 1951                  if (s2)
1952 1952                          rtld_flags |= val;
1953 1953                  else
1954 1954                          rtld_flags &= ~val;
1955 1955          } else if (select & SEL_ACT_RT2) {
1956 1956                  if (s2)
1957 1957                          rtld_flags2 |= val;
1958 1958                  else
1959 1959                          rtld_flags2 &= ~val;
1960 1960          } else if (select & SEL_ACT_STR) {
1961 1961                  if (env_flags & ENV_TYP_NULL)
1962 1962                          *str = NULL;
1963 1963                  else
1964 1964                          *str = s2;
1965 1965          } else if (select & SEL_ACT_LML) {
1966 1966                  if (s2)
1967 1967                          *lmflags |= val;
1968 1968                  else
1969 1969                          *lmflags &= ~val;
1970 1970          } else if (select & SEL_ACT_LMLT) {
1971 1971                  if (s2)
1972 1972                          *lmtflags |= val;
1973 1973                  else
1974 1974                          *lmtflags &= ~val;
1975 1975          } else if (select & SEL_ACT_SPEC_1) {
1976 1976                  /*
1977 1977                   * variable is either ENV_FLG_FLAGS or ENV_FLG_LIBPATH
1978 1978                   */
1979 1979                  if (env_flags & ENV_TYP_NULL)
1980 1980                          *str = NULL;
1981 1981                  else
1982 1982                          *str = s2;
1983 1983                  if ((select & SEL_REPLACE) && (env_flags & ENV_TYP_CONFIG)) {
1984 1984                          if (s2) {
1985 1985                                  if (variable == ENV_FLG_FLAGS)
1986 1986                                          env_info |= ENV_INF_FLAGCFG;
1987 1987                                  else
1988 1988                                          env_info |= ENV_INF_PATHCFG;
1989 1989                          } else {
1990 1990                                  if (variable == ENV_FLG_FLAGS)
1991 1991                                          env_info &= ~ENV_INF_FLAGCFG;
1992 1992                                  else
1993 1993                                          env_info &= ~ENV_INF_PATHCFG;
1994 1994                          }
1995 1995                  }
1996 1996          } else if (select & SEL_ACT_SPEC_2) {
1997 1997                  /*
1998 1998                   * variables can be: ENV_FLG_
1999 1999                   *      AUDIT_ARGS, BINDING, CONFGEN, LOADFLTR, PROFILE,
2000 2000                   *      SIGNAL, TRACE_OBJS
2001 2001                   */
2002 2002                  switch (variable) {
2003 2003                  case ENV_FLG_AUDIT_ARGS:
2004 2004                          if (s2) {
2005 2005                                  audit_argcnt = atoi(s2);
2006 2006                                  audit_argcnt += audit_argcnt % 2;
2007 2007                          } else
2008 2008                                  audit_argcnt = 0;
2009 2009                          break;
2010 2010                  case ENV_FLG_BINDINGS:
2011 2011                          if (s2)
2012 2012                                  rpl_debug = MSG_ORIG(MSG_TKN_BINDINGS);
2013 2013                          else
2014 2014                                  rpl_debug = NULL;
2015 2015                          break;
2016 2016                  case ENV_FLG_CONFGEN:
2017 2017                          if (s2) {
2018 2018                                  rtld_flags |= RT_FL_CONFGEN;
2019 2019                                  *lmflags |= LML_FLG_IGNRELERR;
2020 2020                          } else {
2021 2021                                  rtld_flags &= ~RT_FL_CONFGEN;
2022 2022                                  *lmflags &= ~LML_FLG_IGNRELERR;
2023 2023                          }
2024 2024                          break;
2025 2025                  case ENV_FLG_LOADFLTR:
2026 2026                          if (s2) {
2027 2027                                  *lmtflags |= LML_TFLG_LOADFLTR;
2028 2028                                  if (*s2 == '2')
2029 2029                                          rtld_flags |= RT_FL_WARNFLTR;
2030 2030                          } else {
2031 2031                                  *lmtflags &= ~LML_TFLG_LOADFLTR;
2032 2032                                  rtld_flags &= ~RT_FL_WARNFLTR;
2033 2033                          }
2034 2034                          break;
2035 2035                  case ENV_FLG_PROFILE:
2036 2036                          profile_name = s2;
2037 2037                          if (s2) {
2038 2038                                  if (strcmp(s2, MSG_ORIG(MSG_FIL_RTLD)) == 0) {
2039 2039                                          return;
2040 2040                                  }
2041 2041                                  /* BEGIN CSTYLED */
2042 2042                                  if (rtld_flags & RT_FL_SECURE) {
2043 2043                                          profile_lib =
2044 2044  #if     defined(_ELF64)
2045 2045                                              MSG_ORIG(MSG_PTH_LDPROFSE_64);
2046 2046  #else
2047 2047                                              MSG_ORIG(MSG_PTH_LDPROFSE);
2048 2048  #endif
2049 2049                                  } else {
2050 2050                                          profile_lib =
2051 2051  #if     defined(_ELF64)
2052 2052                                              MSG_ORIG(MSG_PTH_LDPROF_64);
2053 2053  #else
2054 2054                                              MSG_ORIG(MSG_PTH_LDPROF);
2055 2055  #endif
2056 2056                                  }
2057 2057                                  /* END CSTYLED */
2058 2058                          } else
2059 2059                                  profile_lib = NULL;
2060 2060                          break;
2061 2061                  case ENV_FLG_SIGNAL:
2062 2062                          killsig = s2 ? atoi(s2) : SIGKILL;
2063 2063                          break;
2064 2064                  case ENV_FLG_TRACE_OBJS:
2065 2065                          if (s2) {
2066 2066                                  *lmflags |= LML_FLG_TRC_ENABLE;
2067 2067                                  if (*s2 == '2')
2068 2068                                          *lmflags |= LML_FLG_TRC_LDDSTUB;
2069 2069                          } else
2070 2070                                  *lmflags &=
2071 2071                                      ~(LML_FLG_TRC_ENABLE | LML_FLG_TRC_LDDSTUB);
2072 2072                          break;
2073 2073                  }
2074 2074          }
2075 2075  }
2076 2076  
2077 2077  /*
2078 2078   * Determine whether we have an architecture specific environment variable.
2079 2079   * If we do, and we're the wrong architecture, it'll just get ignored.
2080 2080   * Otherwise the variable is processed in it's architecture neutral form.
2081 2081   */
2082 2082  static int
2083 2083  ld_arch_env(const char *s1, size_t *len)
2084 2084  {
2085 2085          size_t  _len = *len - 3;
2086 2086  
2087 2087          if (s1[_len++] == '_') {
2088 2088                  if ((s1[_len] == '3') && (s1[_len + 1] == '2')) {
2089 2089  #if     defined(_ELF64)
2090 2090                          return (ENV_TYP_IGNORE);
2091 2091  #else
2092 2092                          *len = *len - 3;
2093 2093                          return (ENV_TYP_ISA);
2094 2094  #endif
2095 2095                  }
2096 2096                  if ((s1[_len] == '6') && (s1[_len + 1] == '4')) {
2097 2097  #if     defined(_ELF64)
2098 2098                          *len = *len - 3;
2099 2099                          return (ENV_TYP_ISA);
2100 2100  #else
2101 2101                          return (ENV_TYP_IGNORE);
2102 2102  #endif
2103 2103                  }
2104 2104          }
2105 2105          return (0);
2106 2106  }
2107 2107  
2108 2108  /*
2109 2109   * Process an LD_FLAGS environment variable.  The value can be a comma
2110 2110   * separated set of tokens, which are sent (in upper case) into the generic
2111 2111   * LD_XXXX environment variable engine.  For example:
2112 2112   *
2113 2113   *      LD_FLAGS=bind_now=              ->      LD_BIND_NOW=
2114 2114   *      LD_FLAGS=bind_now               ->      LD_BIND_NOW=1
2115 2115   *      LD_FLAGS=library_path=          ->      LD_LIBRARY_PATH=
2116 2116   *      LD_FLAGS=library_path=/foo:.    ->      LD_LIBRARY_PATH=/foo:.
2117 2117   *      LD_FLAGS=debug=files:detail     ->      LD_DEBUG=files:detail
2118 2118   * or
2119 2119   *      LD_FLAGS=bind_now,library_path=/foo:.,debug=files:detail
2120 2120   */
2121 2121  static int
2122 2122  ld_flags_env(const char *str, Word *lmflags, Word *lmtflags,
2123 2123      uint_t env_flags, int aout)
2124 2124  {
2125 2125          char    *nstr, *sstr, *estr = NULL;
2126 2126          size_t  nlen, len;
2127 2127  
2128 2128          if (str == NULL)
2129 2129                  return (0);
2130 2130  
2131 2131          /*
2132 2132           * Create a new string as we're going to transform the token(s) into
2133 2133           * uppercase and separate tokens with nulls.
2134 2134           */
2135 2135          len = strlen(str);
2136 2136          if ((nstr = malloc(len + 1)) == NULL)
2137 2137                  return (1);
2138 2138          (void) strcpy(nstr, str);
2139 2139  
2140 2140          for (sstr = nstr; sstr; sstr++, len--) {
2141 2141                  int     flags = 0;
2142 2142  
2143 2143                  if ((*sstr != '\0') && (*sstr != ',')) {
2144 2144                          if (estr == NULL) {
2145 2145                                  if (*sstr == '=')
2146 2146                                          estr = sstr;
2147 2147                                  else {
2148 2148                                          /*
2149 2149                                           * Translate token to uppercase.  Don't
2150 2150                                           * use toupper(3C) as including this
2151 2151                                           * code doubles the size of ld.so.1.
2152 2152                                           */
2153 2153                                          if ((*sstr >= 'a') && (*sstr <= 'z'))
2154 2154                                                  *sstr = *sstr - ('a' - 'A');
2155 2155                                  }
2156 2156                          }
2157 2157                          continue;
2158 2158                  }
2159 2159  
2160 2160                  *sstr = '\0';
2161 2161  
2162 2162                  /*
2163 2163                   * Have we discovered an "=" string.
2164 2164                   */
2165 2165                  if (estr) {
2166 2166                          nlen = estr - nstr;
2167 2167  
2168 2168                          /*
2169 2169                           * If this is an unqualified "=", then this variable
2170 2170                           * is intended to ensure a feature is disabled.
2171 2171                           */
2172 2172                          if ((*++estr == '\0') || (*estr == ','))
2173 2173                                  estr = NULL;
2174 2174                  } else {
2175 2175                          nlen = sstr - nstr;
2176 2176  
2177 2177                          /*
2178 2178                           * If there is no "=" found, fabricate a boolean
2179 2179                           * definition for any unqualified variable.  Thus,
2180 2180                           * LD_FLAGS=bind_now is represented as BIND_NOW=1.
2181 2181                           * The value "1" is sufficient to assert any boolean
2182 2182                           * variables.  Setting of ENV_TYP_NULL ensures any
2183 2183                           * string usage is reset to a NULL string, thus
2184 2184                           * LD_FLAGS=library_path is equivalent to
2185 2185                           * LIBRARY_PATH='\0'.
2186 2186                           */
2187 2187                          flags |= ENV_TYP_NULL;
2188 2188                          estr = (char *)MSG_ORIG(MSG_STR_ONE);
2189 2189                  }
2190 2190  
2191 2191                  /*
2192 2192                   * Determine whether the environment variable is 32- or 64-bit
2193 2193                   * specific.  The length, len, will reflect the architecture
2194 2194                   * neutral portion of the string.
2195 2195                   */
2196 2196                  if ((flags |= ld_arch_env(nstr, &nlen)) != ENV_TYP_IGNORE) {
2197 2197                          ld_generic_env(nstr, nlen, estr, lmflags,
2198 2198                              lmtflags, (env_flags | flags), aout);
2199 2199                  }
2200 2200                  if (len == 0)
2201 2201                          break;
2202 2202  
2203 2203                  nstr = sstr + 1;
2204 2204                  estr = NULL;
2205 2205          }
2206 2206  
2207 2207          return (0);
2208 2208  }
2209 2209  
2210 2210  /*
2211 2211   * Variant of getopt(), intended for use when ld.so.1 is invoked directly
2212 2212   * from the command line.  The only command line option allowed is -e followed
2213 2213   * by a runtime linker environment variable.
2214 2214   */
2215 2215  int
2216 2216  rtld_getopt(char **argv, char ***envp, auxv_t **auxv, Word *lmflags,
2217 2217      Word *lmtflags, int aout)
2218 2218  {
2219 2219          int     ndx;
2220 2220  
2221 2221          for (ndx = 1; argv[ndx]; ndx++) {
2222 2222                  char    *str;
2223 2223  
2224 2224                  if (argv[ndx][0] != '-')
2225 2225                          break;
2226 2226  
2227 2227                  if (argv[ndx][1] == '\0') {
2228 2228                          ndx++;
2229 2229                          break;
2230 2230                  }
2231 2231  
2232 2232                  if (argv[ndx][1] != 'e')
2233 2233                          return (1);
2234 2234  
2235 2235                  if (argv[ndx][2] == '\0') {
2236 2236                          ndx++;
2237 2237                          if (argv[ndx] == NULL)
2238 2238                                  return (1);
2239 2239                          str = argv[ndx];
2240 2240                  } else
2241 2241                          str = &argv[ndx][2];
2242 2242  
2243 2243                  /*
2244 2244                   * If the environment variable starts with LD_, strip the LD_.
2245 2245                   * Otherwise, take things as is.  Indicate that this variable
2246 2246                   * originates from the command line, as these variables take
2247 2247                   * precedence over any environment variables, or configuration
2248 2248                   * file variables.
2249 2249                   */
2250 2250                  if ((str[0] == 'L') && (str[1] == 'D') && (str[2] == '_') &&
2251 2251                      (str[3] != '\0'))
2252 2252                          str += 3;
2253 2253                  if (ld_flags_env(str, lmflags, lmtflags,
2254 2254                      ENV_TYP_CMDLINE, aout) == 1)
2255 2255                          return (1);
2256 2256          }
2257 2257  
2258 2258          /*
2259 2259           * Make sure an object file has been specified.
2260 2260           */
2261 2261          if (argv[ndx] == NULL)
2262 2262                  return (1);
2263 2263  
2264 2264          /*
2265 2265           * Having gotten the arguments, clean ourselves off of the stack.
2266 2266           * This results in a process that looks as if it was executed directly
2267 2267           * from the application.
2268 2268           */
2269 2269          stack_cleanup(argv, envp, auxv, ndx);
2270 2270          return (0);
2271 2271  }
2272 2272  
2273 2273  /*
2274 2274   * Process a single LD_XXXX string.
2275 2275   */
2276 2276  static void
2277 2277  ld_str_env(const char *s1, Word *lmflags, Word *lmtflags, uint_t env_flags,
2278 2278      int aout)
2279 2279  {
2280 2280          const char      *s2;
2281 2281          size_t          len;
2282 2282          int             flags;
2283 2283  
2284 2284          /*
2285 2285           * In a branded process we must ignore all LD_XXXX variables because
2286 2286           * they are intended for the brand's linker.  To affect the native
2287 2287           * linker, use LD_BRAND_XXXX instead.
2288 2288           */
2289 2289          if (rtld_flags2 & RT_FL2_BRANDED) {
2290 2290                  if (strncmp(s1, MSG_ORIG(MSG_LD_BRAND_PREFIX),
2291 2291                      MSG_LD_BRAND_PREFIX_SIZE) != 0)
2292 2292                          return;
2293 2293                  s1 += MSG_LD_BRAND_PREFIX_SIZE;
2294 2294          }
2295 2295  
2296 2296          /*
2297 2297           * Variables with no value (ie. LD_XXXX=) turn a capability off.
2298 2298           */
2299 2299          if ((s2 = strchr(s1, '=')) == NULL) {
2300 2300                  len = strlen(s1);
2301 2301                  s2 = NULL;
2302 2302          } else if (*++s2 == '\0') {
2303 2303                  len = strlen(s1) - 1;
2304 2304                  s2 = NULL;
2305 2305          } else {
2306 2306                  len = s2 - s1 - 1;
2307 2307                  while (conv_strproc_isspace(*s2))
2308 2308                          s2++;
2309 2309          }
2310 2310  
2311 2311          /*
2312 2312           * Determine whether the environment variable is 32-bit or 64-bit
2313 2313           * specific.  The length, len, will reflect the architecture neutral
2314 2314           * portion of the string.
2315 2315           */
2316 2316          if ((flags = ld_arch_env(s1, &len)) == ENV_TYP_IGNORE)
2317 2317                  return;
2318 2318          env_flags |= flags;
2319 2319  
2320 2320          ld_generic_env(s1, len, s2, lmflags, lmtflags, env_flags, aout);
2321 2321  }
2322 2322  
2323 2323  /*
2324 2324   * Internal getenv routine.  Called immediately after ld.so.1 initializes
2325 2325   * itself to process any locale specific environment variables, and collect
2326 2326   * any LD_XXXX variables for later processing.
2327 2327   */
2328 2328  #define LOC_LANG        1
2329 2329  #define LOC_MESG        2
2330 2330  #define LOC_ALL         3
2331 2331  
2332 2332  int
2333 2333  readenv_user(const char **envp, APlist **ealpp)
2334 2334  {
2335 2335          char            *locale;
2336 2336          const char      *s1;
2337 2337          int             loc = 0;
2338 2338  
2339 2339          for (s1 = *envp; s1; envp++, s1 = *envp) {
2340 2340                  const char      *s2;
2341 2341  
2342 2342                  if (*s1++ != 'L')
2343 2343                          continue;
2344 2344  
2345 2345                  /*
2346 2346                   * See if we have any locale environment settings.  These
2347 2347                   * environment variables have a precedence, LC_ALL is higher
2348 2348                   * than LC_MESSAGES which is higher than LANG.
2349 2349                   */
2350 2350                  s2 = s1;
2351 2351                  if ((*s2++ == 'C') && (*s2++ == '_') && (*s2 != '\0')) {
2352 2352                          if (strncmp(s2, MSG_ORIG(MSG_LC_ALL),
2353 2353                              MSG_LC_ALL_SIZE) == 0) {
2354 2354                                  s2 += MSG_LC_ALL_SIZE;
2355 2355                                  if ((*s2 != '\0') && (loc < LOC_ALL)) {
2356 2356                                          glcs[CI_LCMESSAGES].lc_un.lc_ptr =
2357 2357                                              (char *)s2;
2358 2358                                          loc = LOC_ALL;
2359 2359                                  }
2360 2360                          } else if (strncmp(s2, MSG_ORIG(MSG_LC_MESSAGES),
2361 2361                              MSG_LC_MESSAGES_SIZE) == 0) {
2362 2362                                  s2 += MSG_LC_MESSAGES_SIZE;
2363 2363                                  if ((*s2 != '\0') && (loc < LOC_MESG)) {
2364 2364                                          glcs[CI_LCMESSAGES].lc_un.lc_ptr =
2365 2365                                              (char *)s2;
2366 2366                                          loc = LOC_MESG;
2367 2367                                  }
2368 2368                          }
2369 2369                          continue;
2370 2370                  }
2371 2371  
2372 2372                  s2 = s1;
2373 2373                  if ((*s2++ == 'A') && (*s2++ == 'N') && (*s2++ == 'G') &&
2374 2374                      (*s2++ == '=') && (*s2 != '\0') && (loc < LOC_LANG)) {
2375 2375                          glcs[CI_LCMESSAGES].lc_un.lc_ptr = (char *)s2;
2376 2376                          loc = LOC_LANG;
2377 2377                          continue;
2378 2378                  }
2379 2379  
2380 2380                  /*
2381 2381                   * Pick off any LD_XXXX environment variables.
2382 2382                   */
2383 2383                  if ((*s1++ == 'D') && (*s1++ == '_') && (*s1 != '\0')) {
2384 2384                          if (aplist_append(ealpp, s1, AL_CNT_ENVIRON) == NULL)
2385 2385                                  return (1);
2386 2386                  }
2387 2387          }
2388 2388  
2389 2389          /*
2390 2390           * If we have a locale setting make sure it's worth processing further.
2391 2391           * C and POSIX locales don't need any processing.  In addition, to
2392 2392           * ensure no one escapes the /usr/lib/locale hierarchy, don't allow
2393 2393           * the locale to contain a segment that leads upward in the file system
2394 2394           * hierarchy (i.e. no '..' segments).   Given that we'll be confined to
2395 2395           * the /usr/lib/locale hierarchy, there is no need to extensively
2396 2396           * validate the mode or ownership of any message file (as libc's
2397 2397           * generic handling of message files does), or be concerned with
2398 2398           * symbolic links that might otherwise send us elsewhere.  Duplicate
2399 2399           * the string so that new locale setting can generically cleanup any
2400 2400           * previous locales.
2401 2401           */
2402 2402          if ((locale = glcs[CI_LCMESSAGES].lc_un.lc_ptr) != NULL) {
2403 2403                  if (((*locale == 'C') && (*(locale + 1) == '\0')) ||
2404 2404                      (strcmp(locale, MSG_ORIG(MSG_TKN_POSIX)) == 0) ||
2405 2405                      (strstr(locale, MSG_ORIG(MSG_TKN_DOTDOT)) != NULL))
2406 2406                          glcs[CI_LCMESSAGES].lc_un.lc_ptr = NULL;
2407 2407                  else
2408 2408                          glcs[CI_LCMESSAGES].lc_un.lc_ptr = strdup(locale);
2409 2409          }
2410 2410          return (0);
2411 2411  }
2412 2412  
2413 2413  /*
2414 2414   * Process any LD_XXXX environment variables collected by readenv_user().
2415 2415   */
2416 2416  int
2417 2417  procenv_user(APlist *ealp, Word *lmflags, Word *lmtflags, int aout)
2418 2418  {
2419 2419          Aliste          idx;
2420 2420          const char      *s1;
2421 2421  
2422 2422          for (APLIST_TRAVERSE(ealp, idx, s1))
2423 2423                  ld_str_env(s1, lmflags, lmtflags, 0, aout);
2424 2424  
2425 2425          /*
2426 2426           * Having collected the best representation of any LD_FLAGS, process
2427 2427           * these strings.
2428 2428           */
2429 2429          if (rpl_ldflags) {
2430 2430                  if (ld_flags_env(rpl_ldflags, lmflags, lmtflags, 0, aout) == 1)
2431 2431                          return (1);
2432 2432                  rpl_ldflags = NULL;
2433 2433          }
2434 2434  
2435 2435          /*
2436 2436           * Don't allow environment controlled auditing when tracing or if
2437 2437           * explicitly disabled.  Trigger all tracing modes from
2438 2438           * LML_FLG_TRC_ENABLE.
2439 2439           */
2440 2440          if ((*lmflags & LML_FLG_TRC_ENABLE) || (rtld_flags & RT_FL_NOAUDIT))
2441 2441                  rpl_audit = profile_lib = profile_name = NULL;
2442 2442          if ((*lmflags & LML_FLG_TRC_ENABLE) == 0)
2443 2443                  *lmflags &= ~LML_MSK_TRC;
2444 2444  
2445 2445          /*
2446 2446           * If both LD_BIND_NOW and LD_BIND_LAZY are specified, the former wins.
2447 2447           */
2448 2448          if ((rtld_flags2 & (RT_FL2_BINDNOW | RT_FL2_BINDLAZY)) ==
2449 2449              (RT_FL2_BINDNOW | RT_FL2_BINDLAZY))
2450 2450                  rtld_flags2 &= ~RT_FL2_BINDLAZY;
2451 2451  
2452 2452          /*
2453 2453           * When using ldd(1) -r or -d against an executable, assert -p.
2454 2454           */
2455 2455          if ((*lmflags &
2456 2456              (LML_FLG_TRC_WARN | LML_FLG_TRC_LDDSTUB)) == LML_FLG_TRC_WARN)
2457 2457                  *lmflags |= LML_FLG_TRC_NOPAREXT;
2458 2458  
2459 2459          return (0);
2460 2460  }
2461 2461  
2462 2462  /*
2463 2463   * Configuration environment processing.  Called after the a.out has been
2464 2464   * processed (as the a.out can specify its own configuration file).
2465 2465   */
2466 2466  int
2467 2467  readenv_config(Rtc_env * envtbl, Addr addr, int aout)
2468 2468  {
2469 2469          Word            *lmflags = &(lml_main.lm_flags);
2470 2470          Word            *lmtflags = &(lml_main.lm_tflags);
2471 2471  
2472 2472          if (envtbl == NULL)
2473 2473                  return (0);
2474 2474  
2475 2475          while (envtbl->env_str) {
2476 2476                  uint_t          env_flags = ENV_TYP_CONFIG;
2477 2477                  const char      *s1 = (const char *)(envtbl->env_str + addr);
2478 2478  
2479 2479                  if (envtbl->env_flags & RTC_ENV_PERMANT)
2480 2480                          env_flags |= ENV_TYP_PERMANT;
2481 2481  
2482 2482                  if ((*s1++ == 'L') && (*s1++ == 'D') &&
2483 2483                      (*s1++ == '_') && (*s1 != '\0'))
2484 2484                          ld_str_env(s1, lmflags, lmtflags, env_flags, 0);
2485 2485  
2486 2486                  envtbl++;
2487 2487          }
2488 2488  
2489 2489          /*
2490 2490           * Having collected the best representation of any LD_FLAGS, process
2491 2491           * these strings.
2492 2492           */
2493 2493          if (ld_flags_env(rpl_ldflags, lmflags, lmtflags, 0, aout) == 1)
2494 2494                  return (1);
2495 2495          if (ld_flags_env(prm_ldflags, lmflags, lmtflags, ENV_TYP_CONFIG,
2496 2496              aout) == 1)
2497 2497                  return (1);
2498 2498  
2499 2499          /*
2500 2500           * Don't allow environment controlled auditing when tracing or if
2501 2501           * explicitly disabled.  Trigger all tracing modes from
2502 2502           * LML_FLG_TRC_ENABLE.
2503 2503           */
2504 2504          if ((*lmflags & LML_FLG_TRC_ENABLE) || (rtld_flags & RT_FL_NOAUDIT))
2505 2505                  prm_audit = profile_lib = profile_name = NULL;
2506 2506          if ((*lmflags & LML_FLG_TRC_ENABLE) == 0)
2507 2507                  *lmflags &= ~LML_MSK_TRC;
2508 2508  
2509 2509          return (0);
2510 2510  }
2511 2511  
2512 2512  int
2513 2513  dowrite(Prfbuf * prf)
2514 2514  {
2515 2515          /*
2516 2516           * We do not have a valid file descriptor, so we are unable
2517 2517           * to flush the buffer.
2518 2518           */
2519 2519          if (prf->pr_fd == -1)
2520 2520                  return (0);
2521 2521          (void) write(prf->pr_fd, prf->pr_buf, prf->pr_cur - prf->pr_buf);
2522 2522          prf->pr_cur = prf->pr_buf;
2523 2523          return (1);
2524 2524  }
2525 2525  
2526 2526  /*
2527 2527   * Simplified printing.  The following conversion specifications are supported:
2528 2528   *
2529 2529   *      % [#] [-] [min field width] [. precision] s|d|x|c
2530 2530   *
2531 2531   *
2532 2532   * dorprf takes the output buffer in the form of Prfbuf which permits
2533 2533   * the verification of the output buffer size and the concatenation
2534 2534   * of data to an already existing output buffer.  The Prfbuf
2535 2535   * structure contains the following:
2536 2536   *
2537 2537   *  pr_buf      pointer to the beginning of the output buffer.
2538 2538   *  pr_cur      pointer to the next available byte in the output buffer.  By
2539 2539   *              setting pr_cur ahead of pr_buf you can append to an already
2540 2540   *              existing buffer.
2541 2541   *  pr_len      the size of the output buffer.  By setting pr_len to '0' you
2542 2542   *              disable protection from overflows in the output buffer.
2543 2543   *  pr_fd       a pointer to the file-descriptor the buffer will eventually be
2544 2544   *              output to.  If pr_fd is set to '-1' then it's assumed there is
2545 2545   *              no output buffer, and doprf() will return with an error to
2546 2546   *              indicate an output buffer overflow.  If pr_fd is > -1 then when
2547 2547   *              the output buffer is filled it will be flushed to pr_fd and will
2548 2548   *              then be available for additional data.
2549 2549   */
2550 2550  #define FLG_UT_MINUS    0x0001  /* - */
2551 2551  #define FLG_UT_SHARP    0x0002  /* # */
2552 2552  #define FLG_UT_DOTSEEN  0x0008  /* dot appeared in format spec */
2553 2553  
2554 2554  /*
2555 2555   * This macro is for use from within doprf only.  It is to be used for checking
2556 2556   * the output buffer size and placing characters into the buffer.
2557 2557   */
2558 2558  #define PUTC(c) \
2559 2559          { \
2560 2560                  char tmpc; \
2561 2561                  \
2562 2562                  tmpc = (c); \
2563 2563                  if (bufsiz && (bp >= bufend)) { \
2564 2564                          prf->pr_cur = bp; \
2565 2565                          if (dowrite(prf) == 0) \
2566 2566                                  return (0); \
2567 2567                          bp = prf->pr_cur; \
2568 2568                  } \
2569 2569                  *bp++ = tmpc; \
2570 2570          }
2571 2571  
2572 2572  /*
2573 2573   * Define a local buffer size for building a numeric value - large enough to
2574 2574   * hold a 64-bit value.
2575 2575   */
2576 2576  #define NUM_SIZE        22
2577 2577  
2578 2578  size_t
2579 2579  doprf(const char *format, va_list args, Prfbuf *prf)
2580 2580  {
2581 2581          char    c;
2582 2582          char    *bp = prf->pr_cur;
2583 2583          char    *bufend = prf->pr_buf + prf->pr_len;
2584 2584          size_t  bufsiz = prf->pr_len;
2585 2585  
2586 2586          while ((c = *format++) != '\0') {
2587 2587                  if (c != '%') {
2588 2588                          PUTC(c);
2589 2589                  } else {
2590 2590                          int     base = 0, flag = 0, width = 0, prec = 0;
2591 2591                          size_t  _i;
2592 2592                          int     _c, _n;
2593 2593                          char    *_s;
2594 2594                          int     ls = 0;
2595 2595  again:
2596 2596                          c = *format++;
2597 2597                          switch (c) {
2598 2598                          case '-':
2599 2599                                  flag |= FLG_UT_MINUS;
2600 2600                                  goto again;
2601 2601                          case '#':
2602 2602                                  flag |= FLG_UT_SHARP;
2603 2603                                  goto again;
2604 2604                          case '.':
2605 2605                                  flag |= FLG_UT_DOTSEEN;
2606 2606                                  goto again;
2607 2607                          case '0':
2608 2608                          case '1':
2609 2609                          case '2':
2610 2610                          case '3':
2611 2611                          case '4':
2612 2612                          case '5':
2613 2613                          case '6':
2614 2614                          case '7':
2615 2615                          case '8':
2616 2616                          case '9':
2617 2617                                  if (flag & FLG_UT_DOTSEEN)
2618 2618                                          prec = (prec * 10) + c - '0';
2619 2619                                  else
2620 2620                                          width = (width * 10) + c - '0';
2621 2621                                  goto again;
2622 2622                          case 'x':
2623 2623                          case 'X':
2624 2624                                  base = 16;
2625 2625                                  break;
2626 2626                          case 'd':
2627 2627                          case 'D':
2628 2628                          case 'u':
2629 2629                                  base = 10;
2630 2630                                  flag &= ~FLG_UT_SHARP;
2631 2631                                  break;
2632 2632                          case 'l':
2633 2633                                  base = 10;
2634 2634                                  ls++; /* number of l's (long or long long) */
2635 2635                                  if ((*format == 'l') ||
2636 2636                                      (*format == 'd') || (*format == 'D') ||
2637 2637                                      (*format == 'x') || (*format == 'X') ||
2638 2638                                      (*format == 'o') || (*format == 'O') ||
2639 2639                                      (*format == 'u') || (*format == 'U'))
2640 2640                                          goto again;
2641 2641                                  break;
2642 2642                          case 'o':
2643 2643                          case 'O':
2644 2644                                  base = 8;
2645 2645                                  break;
2646 2646                          case 'c':
2647 2647                                  _c = va_arg(args, int);
2648 2648  
2649 2649                                  for (_i = 24; _i > 0; _i -= 8) {
2650 2650                                          if ((c = ((_c >> _i) & 0x7f)) != 0) {
2651 2651                                                  PUTC(c);
2652 2652                                          }
2653 2653                                  }
2654 2654                                  if ((c = ((_c >> _i) & 0x7f)) != 0) {
2655 2655                                          PUTC(c);
2656 2656                                  }
2657 2657                                  break;
2658 2658                          case 's':
2659 2659                                  _s = va_arg(args, char *);
2660 2660                                  _i = strlen(_s);
2661 2661                                  /* LINTED */
2662 2662                                  _n = (int)(width - _i);
2663 2663                                  if (!prec)
2664 2664                                          /* LINTED */
2665 2665                                          prec = (int)_i;
2666 2666  
2667 2667                                  if (width && !(flag & FLG_UT_MINUS)) {
2668 2668                                          while (_n-- > 0)
2669 2669                                                  PUTC(' ');
2670 2670                                  }
2671 2671                                  while (((c = *_s++) != 0) && prec--) {
2672 2672                                          PUTC(c);
2673 2673                                  }
2674 2674                                  if (width && (flag & FLG_UT_MINUS)) {
2675 2675                                          while (_n-- > 0)
2676 2676                                                  PUTC(' ');
2677 2677                                  }
2678 2678                                  break;
2679 2679                          case '%':
2680 2680                                  PUTC('%');
2681 2681                                  break;
2682 2682                          default:
2683 2683                                  break;
2684 2684                          }
2685 2685  
2686 2686                          /*
2687 2687                           * Numeric processing
2688 2688                           */
2689 2689                          if (base) {
2690 2690                                  char            local[NUM_SIZE];
2691 2691                                  size_t          ssize = 0, psize = 0;
2692 2692                                  const char      *string =
2693 2693                                      MSG_ORIG(MSG_STR_HEXNUM);
2694 2694                                  const char      *prefix =
2695 2695                                      MSG_ORIG(MSG_STR_EMPTY);
2696 2696                                  u_longlong_t    num;
2697 2697  
2698 2698                                  switch (ls) {
2699 2699                                  case 0: /* int */
2700 2700                                          num = (u_longlong_t)
2701 2701                                              va_arg(args, uint_t);
2702 2702                                          break;
2703 2703                                  case 1: /* long */
2704 2704                                          num = (u_longlong_t)
2705 2705                                              va_arg(args, ulong_t);
2706 2706                                          break;
2707 2707                                  case 2: /* long long */
2708 2708                                          num = va_arg(args, u_longlong_t);
2709 2709                                          break;
2710 2710                                  }
2711 2711  
2712 2712                                  if (flag & FLG_UT_SHARP) {
2713 2713                                          if (base == 16) {
2714 2714                                                  prefix = MSG_ORIG(MSG_STR_HEX);
2715 2715                                                  psize = 2;
2716 2716                                          } else {
2717 2717                                                  prefix = MSG_ORIG(MSG_STR_ZERO);
2718 2718                                                  psize = 1;
2719 2719                                          }
2720 2720                                  }
2721 2721                                  if ((base == 10) && (long)num < 0) {
2722 2722                                          prefix = MSG_ORIG(MSG_STR_NEGATE);
2723 2723                                          psize = MSG_STR_NEGATE_SIZE;
2724 2724                                          num = (u_longlong_t)(-(longlong_t)num);
2725 2725                                  }
2726 2726  
2727 2727                                  /*
2728 2728                                   * Convert the numeric value into a local
2729 2729                                   * string (stored in reverse order).
2730 2730                                   */
2731 2731                                  _s = local;
2732 2732                                  do {
2733 2733                                          *_s++ = string[num % base];
2734 2734                                          num /= base;
2735 2735                                          ssize++;
2736 2736                                  } while (num);
2737 2737  
2738 2738                                  ASSERT(ssize < sizeof (local));
2739 2739  
2740 2740                                  /*
2741 2741                                   * Provide any precision or width padding.
2742 2742                                   */
2743 2743                                  if (prec) {
2744 2744                                          /* LINTED */
2745 2745                                          _n = (int)(prec - ssize);
2746 2746                                          while ((_n-- > 0) &&
2747 2747                                              (ssize < sizeof (local))) {
2748 2748                                                  *_s++ = '0';
2749 2749                                                  ssize++;
2750 2750                                          }
2751 2751                                  }
2752 2752                                  if (width && !(flag & FLG_UT_MINUS)) {
2753 2753                                          /* LINTED */
2754 2754                                          _n = (int)(width - ssize - psize);
2755 2755                                          while (_n-- > 0) {
2756 2756                                                  PUTC(' ');
2757 2757                                          }
2758 2758                                  }
2759 2759  
2760 2760                                  /*
2761 2761                                   * Print any prefix and the numeric string
2762 2762                                   */
2763 2763                                  while (*prefix)
2764 2764                                          PUTC(*prefix++);
2765 2765                                  do {
2766 2766                                          PUTC(*--_s);
2767 2767                                  } while (_s > local);
2768 2768  
2769 2769                                  /*
2770 2770                                   * Provide any width padding.
2771 2771                                   */
2772 2772                                  if (width && (flag & FLG_UT_MINUS)) {
2773 2773                                          /* LINTED */
2774 2774                                          _n = (int)(width - ssize - psize);
2775 2775                                          while (_n-- > 0)
2776 2776                                                  PUTC(' ');
2777 2777                                  }
2778 2778                          }
2779 2779                  }
2780 2780          }
2781 2781  
2782 2782          PUTC('\0');
2783 2783          prf->pr_cur = bp;
2784 2784          return (1);
2785 2785  }
2786 2786  
2787 2787  static int
2788 2788  doprintf(const char *format, va_list args, Prfbuf *prf)
2789 2789  {
2790 2790          char    *ocur = prf->pr_cur;
2791 2791  
2792 2792          if (doprf(format, args, prf) == 0)
2793 2793                  return (0);
2794 2794          /* LINTED */
2795 2795          return ((int)(prf->pr_cur - ocur));
2796 2796  }
2797 2797  
2798 2798  /* VARARGS2 */
2799 2799  int
2800 2800  sprintf(char *buf, const char *format, ...)
2801 2801  {
2802 2802          va_list args;
2803 2803          int     len;
2804 2804          Prfbuf  prf;
2805 2805  
2806 2806          va_start(args, format);
2807 2807          prf.pr_buf = prf.pr_cur = buf;
2808 2808          prf.pr_len = 0;
2809 2809          prf.pr_fd = -1;
2810 2810          len = doprintf(format, args, &prf);
2811 2811          va_end(args);
2812 2812  
2813 2813          /*
2814 2814           * sprintf() return value excludes the terminating null byte.
2815 2815           */
2816 2816          return (len - 1);
2817 2817  }
2818 2818  
2819 2819  /* VARARGS3 */
2820 2820  int
2821 2821  snprintf(char *buf, size_t n, const char *format, ...)
2822 2822  {
2823 2823          va_list args;
2824 2824          int     len;
2825 2825          Prfbuf  prf;
2826 2826  
2827 2827          va_start(args, format);
2828 2828          prf.pr_buf = prf.pr_cur = buf;
2829 2829          prf.pr_len = n;
2830 2830          prf.pr_fd = -1;
2831 2831          len = doprintf(format, args, &prf);
2832 2832          va_end(args);
2833 2833  
2834 2834          return (len);
2835 2835  }
2836 2836  
2837 2837  /* VARARGS2 */
2838 2838  int
2839 2839  bufprint(Prfbuf *prf, const char *format, ...)
2840 2840  {
2841 2841          va_list args;
2842 2842          int     len;
2843 2843  
2844 2844          va_start(args, format);
2845 2845          len = doprintf(format, args, prf);
2846 2846          va_end(args);
2847 2847  
2848 2848          return (len);
2849 2849  }
2850 2850  
2851 2851  /*PRINTFLIKE1*/
2852 2852  int
2853 2853  printf(const char *format, ...)
2854 2854  {
2855 2855          va_list args;
2856 2856          char    buffer[ERRSIZE];
2857 2857          Prfbuf  prf;
2858 2858  
2859 2859          va_start(args, format);
2860 2860          prf.pr_buf = prf.pr_cur = buffer;
2861 2861          prf.pr_len = ERRSIZE;
2862 2862          prf.pr_fd = 1;
2863 2863          (void) doprf(format, args, &prf);
2864 2864          va_end(args);
2865 2865          /*
2866 2866           * Trim trailing '\0' form buffer
2867 2867           */
2868 2868          prf.pr_cur--;
2869 2869          return (dowrite(&prf));
2870 2870  }
2871 2871  
2872 2872  static char     errbuf[ERRSIZE], *nextptr = errbuf, *prevptr = NULL;
2873 2873  
2874 2874  /*
2875 2875   * All error messages go through eprintf().  During process initialization,
2876 2876   * these messages are directed to the standard error, however once control has
2877 2877   * been passed to the applications code these messages are stored in an internal
2878 2878   * buffer for use with dlerror().  Note, fatal error conditions that may occur
2879 2879   * while running the application will still cause a standard error message, see
2880 2880   * rtldexit() in this file for details.
  
    | ↓ open down ↓ | 2361 lines elided | ↑ open up ↑ | 
2881 2881   * The RT_FL_APPLIC flag serves to indicate the transition between process
2882 2882   * initialization and when the applications code is running.
2883 2883   */
2884 2884  void
2885 2885  veprintf(Lm_list *lml, Error error, const char *format, va_list args)
2886 2886  {
2887 2887          int             overflow = 0;
2888 2888          static int      lock = 0;
2889 2889          Prfbuf          prf;
2890 2890  
2891      -        if (lock || (nextptr == (errbuf + ERRSIZE)))
     2891 +        if (lock || (nextptr > (errbuf + (ERRSIZE - 1))))
2892 2892                  return;
2893 2893  
2894 2894          /*
2895 2895           * Note: this lock is here to prevent the same thread from recursively
2896 2896           * entering itself during a eprintf.  ie: during eprintf malloc() fails
2897 2897           * and we try and call eprintf ... and then malloc() fails ....
2898 2898           */
2899 2899          lock = 1;
2900 2900  
2901 2901          /*
2902 2902           * If we have completed startup initialization, all error messages
2903 2903           * must be saved.  These are reported through dlerror().  If we're
2904 2904           * still in the initialization stage, output the error directly and
2905 2905           * add a newline.
2906 2906           */
2907 2907          prf.pr_buf = prf.pr_cur = nextptr;
2908 2908          prf.pr_len = ERRSIZE - (nextptr - errbuf);
2909 2909  
2910 2910          if ((rtld_flags & RT_FL_APPLIC) == 0)
2911 2911                  prf.pr_fd = 2;
2912 2912          else
2913 2913                  prf.pr_fd = -1;
2914 2914  
2915 2915          if (error > ERR_NONE) {
2916 2916                  if ((error == ERR_FATAL) && (rtld_flags2 & RT_FL2_FTL2WARN))
2917 2917                          error = ERR_WARNING;
2918 2918                  switch (error) {
2919 2919                  case ERR_WARNING_NF:
2920 2920                          if (err_strs[ERR_WARNING_NF] == NULL)
2921 2921                                  err_strs[ERR_WARNING_NF] =
2922 2922                                      MSG_INTL(MSG_ERR_WARNING);
2923 2923                          break;
2924 2924                  case ERR_WARNING:
2925 2925                          if (err_strs[ERR_WARNING] == NULL)
2926 2926                                  err_strs[ERR_WARNING] =
2927 2927                                      MSG_INTL(MSG_ERR_WARNING);
2928 2928                          break;
2929 2929                  case ERR_GUIDANCE:
2930 2930                          if (err_strs[ERR_GUIDANCE] == NULL)
2931 2931                                  err_strs[ERR_GUIDANCE] =
2932 2932                                      MSG_INTL(MSG_ERR_GUIDANCE);
2933 2933                          break;
2934 2934                  case ERR_FATAL:
2935 2935                          if (err_strs[ERR_FATAL] == NULL)
2936 2936                                  err_strs[ERR_FATAL] = MSG_INTL(MSG_ERR_FATAL);
2937 2937                          break;
2938 2938                  case ERR_ELF:
2939 2939                          if (err_strs[ERR_ELF] == NULL)
2940 2940                                  err_strs[ERR_ELF] = MSG_INTL(MSG_ERR_ELF);
2941 2941                          break;
2942 2942                  }
2943 2943                  if (procname) {
2944 2944                          if (bufprint(&prf, MSG_ORIG(MSG_STR_EMSGFOR1),
2945 2945                              rtldname, procname, err_strs[error]) == 0)
2946 2946                                  overflow = 1;
2947 2947                  } else {
2948 2948                          if (bufprint(&prf, MSG_ORIG(MSG_STR_EMSGFOR2),
2949 2949                              rtldname, err_strs[error]) == 0)
2950 2950                                  overflow = 1;
2951 2951                  }
2952 2952                  if (overflow == 0) {
2953 2953                          /*
2954 2954                           * Remove the terminating '\0'.
2955 2955                           */
2956 2956                          prf.pr_cur--;
2957 2957                  }
2958 2958          }
2959 2959  
2960 2960          if ((overflow == 0) && doprf(format, args, &prf) == 0)
2961 2961                  overflow = 1;
2962 2962  
2963 2963          /*
2964 2964           * If this is an ELF error, it will have been generated by a support
2965 2965           * object that has a dependency on libelf.  ld.so.1 doesn't generate any
2966 2966           * ELF error messages as it doesn't interact with libelf.  Determine the
2967 2967           * ELF error string.
2968 2968           */
2969 2969          if ((overflow == 0) && (error == ERR_ELF)) {
2970 2970                  static int              (*elfeno)() = 0;
2971 2971                  static const char       *(*elfemg)();
2972 2972                  const char              *emsg;
2973 2973                  Rt_map                  *dlmp, *lmp = lml_rtld.lm_head;
2974 2974  
2975 2975                  if (NEXT(lmp) && (elfeno == 0)) {
2976 2976                          if (((elfemg = (const char *(*)())dlsym_intn(RTLD_NEXT,
2977 2977                              MSG_ORIG(MSG_SYM_ELFERRMSG),
2978 2978                              lmp, &dlmp)) == NULL) ||
2979 2979                              ((elfeno = (int (*)())dlsym_intn(RTLD_NEXT,
2980 2980                              MSG_ORIG(MSG_SYM_ELFERRNO), lmp, &dlmp)) == NULL))
2981 2981                                  elfeno = 0;
2982 2982                  }
2983 2983  
2984 2984                  /*
2985 2985                   * Lookup the message; equivalent to elf_errmsg(elf_errno()).
2986 2986                   */
2987 2987                  if (elfeno && ((emsg = (* elfemg)((* elfeno)())) != NULL)) {
2988 2988                          prf.pr_cur--;
2989 2989                          if (bufprint(&prf, MSG_ORIG(MSG_STR_EMSGFOR2),
2990 2990                              emsg) == 0)
2991 2991                                  overflow = 1;
2992 2992                  }
2993 2993          }
2994 2994  
2995 2995          /*
2996 2996           * Push out any message that's been built.  Note, in the case of an
2997 2997           * overflow condition, this message may be incomplete, in which case
2998 2998           * make sure any partial string is null terminated.
2999 2999           */
3000 3000          if ((rtld_flags & (RT_FL_APPLIC | RT_FL_SILENCERR)) == 0) {
3001 3001                  *(prf.pr_cur - 1) = '\n';
3002 3002                  (void) dowrite(&prf);
3003 3003          }
3004 3004          if (overflow)
3005 3005                  *(prf.pr_cur - 1) = '\0';
3006 3006  
3007 3007          DBG_CALL(Dbg_util_str(lml, nextptr));
3008 3008  
3009 3009          /*
3010 3010           * Determine if there was insufficient space left in the buffer to
3011 3011           * complete the message.  If so, we'll have printed out as much as had
3012 3012           * been processed if we're not yet executing the application.
3013 3013           * Otherwise, there will be some debugging diagnostic indicating
3014 3014           * as much of the error message as possible.  Write out a final buffer
3015 3015           * overflow diagnostic - unlocalized, so we don't chance more errors.
3016 3016           */
3017 3017          if (overflow) {
3018 3018                  char    *str = (char *)MSG_INTL(MSG_EMG_BUFOVRFLW);
3019 3019  
3020 3020                  if ((rtld_flags & RT_FL_SILENCERR) == 0) {
3021 3021                          lasterr = str;
3022 3022  
3023 3023                          if ((rtld_flags & RT_FL_APPLIC) == 0) {
3024 3024                                  (void) write(2, str, strlen(str));
3025 3025                                  (void) write(2, MSG_ORIG(MSG_STR_NL),
3026 3026                                      MSG_STR_NL_SIZE);
3027 3027                          }
3028 3028                  }
3029 3029                  DBG_CALL(Dbg_util_str(lml, str));
3030 3030  
3031 3031                  lock = 0;
3032 3032                  nextptr = errbuf + ERRSIZE;
3033 3033                  return;
3034 3034          }
3035 3035  
3036 3036          /*
3037 3037           * If the application has started, then error messages are being saved
3038 3038           * for retrieval by dlerror(), or possible flushing from rtldexit() in
3039 3039           * the case of a fatal error.  In this case, establish the next error
3040 3040           * pointer.  If we haven't started the application, the whole message
3041 3041           * buffer can be reused.
3042 3042           */
3043 3043          if ((rtld_flags & RT_FL_SILENCERR) == 0) {
3044 3044                  lasterr = nextptr;
3045 3045  
3046 3046                  /*
3047 3047                   * Note, should we encounter an error such as ENOMEM, there may
3048 3048                   * be a number of the same error messages (ie. an operation
3049 3049                   * fails with ENOMEM, and then the attempts to construct the
3050 3050                   * error message itself, which incurs additional ENOMEM errors).
3051 3051                   * Compare any previous error message with the one we've just
3052 3052                   * created to prevent any duplication clutter.
3053 3053                   */
3054 3054                  if ((rtld_flags & RT_FL_APPLIC) &&
3055 3055                      ((prevptr == NULL) || (strcmp(prevptr, nextptr) != 0))) {
3056 3056                          prevptr = nextptr;
3057 3057                          nextptr = prf.pr_cur;
3058 3058                          *nextptr = '\0';
3059 3059                  }
3060 3060          }
3061 3061          lock = 0;
3062 3062  }
3063 3063  
3064 3064  /*PRINTFLIKE3*/
3065 3065  void
3066 3066  eprintf(Lm_list *lml, Error error, const char *format, ...)
3067 3067  {
3068 3068          va_list         args;
3069 3069  
3070 3070          va_start(args, format);
3071 3071          veprintf(lml, error, format, args);
3072 3072          va_end(args);
3073 3073  }
3074 3074  
3075 3075  /*
3076 3076   * Provide assfail() for ASSERT() statements.  See <sys/debug.h> for further
3077 3077   * details.
3078 3078   */
3079 3079  int
3080 3080  assfail(const char *a, const char *f, int l)
3081 3081  {
3082 3082          (void) printf("assertion failed: %s, file: %s, line: %d\n", a, f, l);
3083 3083          (void) _lwp_kill(_lwp_self(), SIGABRT);
3084 3084          return (0);
3085 3085  }
3086 3086  
3087 3087  void
3088 3088  assfail3(const char *msg, uintmax_t a, const char *op, uintmax_t b,
3089 3089      const char *f, int l)
3090 3090  {
3091 3091          (void) printf("assertion failed: %s (0x%llx %s 0x%llx), "
3092 3092              "file: %s, line: %d\n", msg, (unsigned long long)a, op,
3093 3093              (unsigned long long)b, f, l);
3094 3094          (void) _lwp_kill(_lwp_self(), SIGABRT);
3095 3095  }
3096 3096  
3097 3097  /*
3098 3098   * Exit.  If we arrive here with a non zero status it's because of a fatal
3099 3099   * error condition (most commonly a relocation error).  If the application has
3100 3100   * already had control, then the actual fatal error message will have been
3101 3101   * recorded in the dlerror() message buffer.  Print the message before really
3102 3102   * exiting.
3103 3103   */
3104 3104  void
3105 3105  rtldexit(Lm_list * lml, int status)
3106 3106  {
3107 3107          if (status) {
3108 3108                  if (rtld_flags & RT_FL_APPLIC) {
3109 3109                          /*
3110 3110                           * If the error buffer has been used, write out all
3111 3111                           * pending messages - lasterr is simply a pointer to
3112 3112                           * the last message in this buffer.  However, if the
3113 3113                           * buffer couldn't be created at all, lasterr points
3114 3114                           * to a constant error message string.
3115 3115                           */
3116 3116                          if (*errbuf) {
3117 3117                                  char    *errptr = errbuf;
3118 3118                                  char    *errend = errbuf + ERRSIZE;
  
    | ↓ open down ↓ | 217 lines elided | ↑ open up ↑ | 
3119 3119  
3120 3120                                  while ((errptr < errend) && *errptr) {
3121 3121                                          size_t  size = strlen(errptr);
3122 3122                                          (void) write(2, errptr, size);
3123 3123                                          (void) write(2, MSG_ORIG(MSG_STR_NL),
3124 3124                                              MSG_STR_NL_SIZE);
3125 3125                                          errptr += (size + 1);
3126 3126                                  }
3127 3127                          }
3128 3128                          if (lasterr && ((lasterr < errbuf) ||
3129      -                            (lasterr > (errbuf + ERRSIZE)))) {
     3129 +                            (lasterr > (errbuf + (ERRSIZE - 1))))) {
3130 3130                                  (void) write(2, lasterr, strlen(lasterr));
3131 3131                                  (void) write(2, MSG_ORIG(MSG_STR_NL),
3132 3132                                      MSG_STR_NL_SIZE);
3133 3133                          }
3134 3134                  }
3135 3135                  leave(lml, 0);
3136 3136                  (void) _lwp_kill(_lwp_self(), killsig);
3137 3137          }
3138 3138          _exit(status);
3139 3139  }
3140 3140  
3141 3141  /*
3142 3142   * Map anonymous memory via MAP_ANON (added in Solaris 8).
3143 3143   */
3144 3144  void *
3145 3145  dz_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
3146 3146  {
3147 3147          caddr_t va;
3148 3148  
3149 3149          if ((va = (caddr_t)mmap(addr, len, prot,
3150 3150              (flags | MAP_ANON), -1, 0)) == MAP_FAILED) {
3151 3151                  int     err = errno;
3152 3152                  eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAPANON),
3153 3153                      strerror(err));
3154 3154                  return (MAP_FAILED);
3155 3155          }
3156 3156          return (va);
3157 3157  }
3158 3158  
3159 3159  static int      nu_fd = FD_UNAVAIL;
3160 3160  
3161 3161  void *
3162 3162  nu_map(Lm_list *lml, caddr_t addr, size_t len, int prot, int flags)
3163 3163  {
3164 3164          caddr_t va;
3165 3165          int     err;
3166 3166  
3167 3167          if (nu_fd == FD_UNAVAIL) {
3168 3168                  if ((nu_fd = open(MSG_ORIG(MSG_PTH_DEVNULL),
3169 3169                      O_RDONLY)) == FD_UNAVAIL) {
3170 3170                          err = errno;
3171 3171                          eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_OPEN),
3172 3172                              MSG_ORIG(MSG_PTH_DEVNULL), strerror(err));
3173 3173                          return (MAP_FAILED);
3174 3174                  }
3175 3175          }
3176 3176  
3177 3177          if ((va = (caddr_t)mmap(addr, len, prot, flags, nu_fd, 0)) ==
3178 3178              MAP_FAILED) {
3179 3179                  err = errno;
3180 3180                  eprintf(lml, ERR_FATAL, MSG_INTL(MSG_SYS_MMAP),
3181 3181                      MSG_ORIG(MSG_PTH_DEVNULL), strerror(err));
3182 3182          }
3183 3183          return (va);
3184 3184  }
3185 3185  
3186 3186  /*
3187 3187   * Generic entry point from user code - simply grabs a lock, and bumps the
3188 3188   * entrance count.
3189 3189   */
3190 3190  int
3191 3191  enter(int flags)
3192 3192  {
3193 3193          if (rt_bind_guard(THR_FLG_RTLD | thr_flg_nolock | flags)) {
3194 3194                  if (!thr_flg_nolock)
3195 3195                          (void) rt_mutex_lock(&rtldlock);
3196 3196                  if (rtld_flags & RT_FL_OPERATION) {
3197 3197                          ld_entry_cnt++;
3198 3198  
3199 3199                          /*
3200 3200                           * Reset the diagnostic time information for each new
3201 3201                           * "operation".  Thus timing diagnostics are relative
3202 3202                           * to entering ld.so.1.
3203 3203                           */
3204 3204                          if (DBG_ISTIME() &&
3205 3205                              (gettimeofday(&DBG_TOTALTIME, NULL) == 0)) {
3206 3206                                  DBG_DELTATIME = DBG_TOTALTIME;
3207 3207                                  DBG_ONRESET();
3208 3208                          }
3209 3209                  }
3210 3210                  return (1);
3211 3211          }
3212 3212          return (0);
3213 3213  }
3214 3214  
3215 3215  /*
3216 3216   * Determine whether a search path has been used.
3217 3217   */
3218 3218  static void
3219 3219  is_path_used(Lm_list *lml, Word unref, int *nl, Alist *alp, const char *obj)
3220 3220  {
3221 3221          Pdesc   *pdp;
3222 3222          Aliste  idx;
3223 3223  
3224 3224          for (ALIST_TRAVERSE(alp, idx, pdp)) {
3225 3225                  const char      *fmt, *name;
3226 3226  
3227 3227                  if ((pdp->pd_plen == 0) || (pdp->pd_flags & PD_FLG_USED))
3228 3228                          continue;
3229 3229  
3230 3230                  /*
3231 3231                   * If this pathname originated from an expanded token, use the
3232 3232                   * original for any diagnostic output.
3233 3233                   */
3234 3234                  if ((name = pdp->pd_oname) == NULL)
3235 3235                          name = pdp->pd_pname;
3236 3236  
3237 3237                  if (unref == 0) {
3238 3238                          if ((*nl)++ == 0)
3239 3239                                  DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
3240 3240                          DBG_CALL(Dbg_unused_path(lml, name, pdp->pd_flags,
3241 3241                              (pdp->pd_flags & PD_FLG_DUPLICAT), obj));
3242 3242                          continue;
3243 3243                  }
3244 3244  
3245 3245                  if (pdp->pd_flags & LA_SER_LIBPATH) {
3246 3246                          if (pdp->pd_flags & LA_SER_CONFIG) {
3247 3247                                  if (pdp->pd_flags & PD_FLG_DUPLICAT)
3248 3248                                          fmt = MSG_INTL(MSG_DUP_LDLIBPATHC);
3249 3249                                  else
3250 3250                                          fmt = MSG_INTL(MSG_USD_LDLIBPATHC);
3251 3251                          } else {
3252 3252                                  if (pdp->pd_flags & PD_FLG_DUPLICAT)
3253 3253                                          fmt = MSG_INTL(MSG_DUP_LDLIBPATH);
3254 3254                                  else
3255 3255                                          fmt = MSG_INTL(MSG_USD_LDLIBPATH);
3256 3256                          }
3257 3257                  } else if (pdp->pd_flags & LA_SER_RUNPATH) {
3258 3258                          fmt = MSG_INTL(MSG_USD_RUNPATH);
3259 3259                  } else
3260 3260                          continue;
3261 3261  
3262 3262                  if ((*nl)++ == 0)
3263 3263                          (void) printf(MSG_ORIG(MSG_STR_NL));
3264 3264                  (void) printf(fmt, name, obj);
3265 3265          }
3266 3266  }
3267 3267  
3268 3268  /*
3269 3269   * Generate diagnostics as to whether an object has been used.  A symbolic
3270 3270   * reference that gets bound to an object marks it as used.  Dependencies that
3271 3271   * are unused when RTLD_NOW is in effect should be removed from future builds
3272 3272   * of an object.  Dependencies that are unused without RTLD_NOW in effect are
3273 3273   * candidates for lazy-loading.
3274 3274   *
3275 3275   * Unreferenced objects identify objects that are defined as dependencies but
3276 3276   * are unreferenced by the caller.  These unreferenced objects may however be
3277 3277   * referenced by other objects within the process, and therefore don't qualify
3278 3278   * as completely unused.  They are still an unnecessary overhead.
3279 3279   *
3280 3280   * Unreferenced runpaths are also captured under ldd -U, or "unused,detail"
3281 3281   * debugging.
3282 3282   */
3283 3283  void
3284 3284  unused(Lm_list *lml)
3285 3285  {
3286 3286          Rt_map          *lmp;
3287 3287          int             nl = 0;
3288 3288          Word            unref, unuse;
3289 3289  
3290 3290          /*
3291 3291           * If we're not tracing unused references or dependencies, or debugging
3292 3292           * there's nothing to do.
3293 3293           */
3294 3294          unref = lml->lm_flags & LML_FLG_TRC_UNREF;
3295 3295          unuse = lml->lm_flags & LML_FLG_TRC_UNUSED;
3296 3296  
3297 3297          if ((unref == 0) && (unuse == 0) && (DBG_ENABLED == 0))
3298 3298                  return;
3299 3299  
3300 3300          /*
3301 3301           * Detect unused global search paths.
3302 3302           */
3303 3303          if (rpl_libdirs)
3304 3304                  is_path_used(lml, unref, &nl, rpl_libdirs, config->c_name);
3305 3305          if (prm_libdirs)
3306 3306                  is_path_used(lml, unref, &nl, prm_libdirs, config->c_name);
3307 3307  
3308 3308          nl = 0;
3309 3309          lmp = lml->lm_head;
3310 3310          if (RLIST(lmp))
3311 3311                  is_path_used(lml, unref, &nl, RLIST(lmp), NAME(lmp));
3312 3312  
3313 3313          /*
3314 3314           * Traverse the link-maps looking for unreferenced or unused
3315 3315           * dependencies.  Ignore the first object on a link-map list, as this
3316 3316           * is always used.
3317 3317           */
3318 3318          nl = 0;
3319 3319          for (lmp = NEXT_RT_MAP(lmp); lmp; lmp = NEXT_RT_MAP(lmp)) {
3320 3320                  /*
3321 3321                   * Determine if this object contains any runpaths that have
3322 3322                   * not been used.
3323 3323                   */
3324 3324                  if (RLIST(lmp))
3325 3325                          is_path_used(lml, unref, &nl, RLIST(lmp), NAME(lmp));
3326 3326  
3327 3327                  /*
3328 3328                   * If tracing unreferenced objects, or under debugging,
3329 3329                   * determine whether any of this objects callers haven't
3330 3330                   * referenced it.
3331 3331                   */
3332 3332                  if (unref || DBG_ENABLED) {
3333 3333                          Bnd_desc        *bdp;
3334 3334                          Aliste          idx;
3335 3335  
3336 3336                          for (APLIST_TRAVERSE(CALLERS(lmp), idx, bdp)) {
3337 3337                                  Rt_map  *clmp;
3338 3338  
3339 3339                                  if (bdp->b_flags & BND_REFER)
3340 3340                                          continue;
3341 3341  
3342 3342                                  clmp = bdp->b_caller;
3343 3343                                  if (FLAGS1(clmp) & FL1_RT_LDDSTUB)
3344 3344                                          continue;
3345 3345  
3346 3346                                  /* BEGIN CSTYLED */
3347 3347                                  if (nl++ == 0) {
3348 3348                                          if (unref)
3349 3349                                              (void) printf(MSG_ORIG(MSG_STR_NL));
3350 3350                                          else
3351 3351                                              DBG_CALL(Dbg_util_nl(lml,
3352 3352                                                  DBG_NL_STD));
3353 3353                                  }
3354 3354  
3355 3355                                  if (unref)
3356 3356                                      (void) printf(MSG_INTL(MSG_LDD_UNREF_FMT),
3357 3357                                          NAME(lmp), NAME(clmp));
3358 3358                                  else
3359 3359                                      DBG_CALL(Dbg_unused_unref(lmp, NAME(clmp)));
3360 3360                                  /* END CSTYLED */
3361 3361                          }
3362 3362                  }
3363 3363  
3364 3364                  /*
3365 3365                   * If tracing unused objects simply display those objects that
3366 3366                   * haven't been referenced by anyone.
3367 3367                   */
3368 3368                  if (FLAGS1(lmp) & FL1_RT_USED)
3369 3369                          continue;
3370 3370  
3371 3371                  if (nl++ == 0) {
3372 3372                          if (unref || unuse)
3373 3373                                  (void) printf(MSG_ORIG(MSG_STR_NL));
3374 3374                          else
3375 3375                                  DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
3376 3376                  }
3377 3377                  if (CYCGROUP(lmp)) {
3378 3378                          if (unref || unuse)
3379 3379                                  (void) printf(MSG_INTL(MSG_LDD_UNCYC_FMT),
3380 3380                                      NAME(lmp), CYCGROUP(lmp));
3381 3381                          else
3382 3382                                  DBG_CALL(Dbg_unused_file(lml, NAME(lmp), 0,
3383 3383                                      CYCGROUP(lmp)));
3384 3384                  } else {
3385 3385                          if (unref || unuse)
3386 3386                                  (void) printf(MSG_INTL(MSG_LDD_UNUSED_FMT),
3387 3387                                      NAME(lmp));
3388 3388                          else
3389 3389                                  DBG_CALL(Dbg_unused_file(lml, NAME(lmp), 0, 0));
3390 3390                  }
3391 3391          }
3392 3392  
3393 3393          DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
3394 3394  }
3395 3395  
3396 3396  /*
3397 3397   * Generic cleanup routine called prior to returning control to the user.
3398 3398   * Ensures that any ld.so.1 specific file descriptors or temporary mapping are
3399 3399   * released, and any locks dropped.
3400 3400   */
3401 3401  void
3402 3402  leave(Lm_list *lml, int flags)
3403 3403  {
3404 3404          /*
3405 3405           * Alert the debuggers that the link-maps are consistent.
3406 3406           */
3407 3407          rd_event(lml, RD_DLACTIVITY, RT_CONSISTENT);
3408 3408  
3409 3409          /*
3410 3410           * Alert any auditors that the link-maps are consistent.
3411 3411           */
3412 3412          if (lml->lm_flags & LML_FLG_ACTAUDIT) {
3413 3413                  audit_activity(lml->lm_head, LA_ACT_CONSISTENT);
3414 3414                  lml->lm_flags &= ~LML_FLG_ACTAUDIT;
3415 3415          }
3416 3416  
3417 3417          if (nu_fd != FD_UNAVAIL) {
3418 3418                  (void) close(nu_fd);
3419 3419                  nu_fd = FD_UNAVAIL;
3420 3420          }
3421 3421  
3422 3422          /*
3423 3423           * Reinitialize error message pointer, and any overflow indication.
3424 3424           */
3425 3425          nextptr = errbuf;
3426 3426          prevptr = NULL;
3427 3427  
3428 3428          /*
3429 3429           * Defragment any freed memory.
3430 3430           */
3431 3431          if (aplist_nitems(free_alp))
3432 3432                  defrag();
3433 3433  
3434 3434          /*
3435 3435           * Don't drop our lock if we are running on our link-map list as
3436 3436           * there's little point in doing so since we are single-threaded.
3437 3437           *
3438 3438           * LML_FLG_HOLDLOCK is set for:
3439 3439           *  -    The ld.so.1's link-map list.
3440 3440           *  -    The auditor's link-map if the environment is pre-UPM.
3441 3441           */
3442 3442          if (lml->lm_flags & LML_FLG_HOLDLOCK)
3443 3443                  return;
3444 3444  
3445 3445          if (rt_bind_clear(0) & THR_FLG_RTLD) {
3446 3446                  if (!thr_flg_nolock)
3447 3447                          (void) rt_mutex_unlock(&rtldlock);
3448 3448                  (void) rt_bind_clear(THR_FLG_RTLD | thr_flg_nolock | flags);
3449 3449          }
3450 3450  }
3451 3451  
3452 3452  int
3453 3453  callable(Rt_map *clmp, Rt_map *dlmp, Grp_hdl *ghp, uint_t slflags)
3454 3454  {
3455 3455          APlist          *calp, *dalp;
3456 3456          Aliste          idx1, idx2;
3457 3457          Grp_hdl         *ghp1, *ghp2;
3458 3458  
3459 3459          /*
3460 3460           * An object can always find symbols within itself.
3461 3461           */
3462 3462          if (clmp == dlmp)
3463 3463                  return (1);
3464 3464  
3465 3465          /*
3466 3466           * The search for a singleton must look in every loaded object.
3467 3467           */
3468 3468          if (slflags & LKUP_SINGLETON)
3469 3469                  return (1);
3470 3470  
3471 3471          /*
3472 3472           * Don't allow an object to bind to an object that is being deleted
3473 3473           * unless the binder is also being deleted.
3474 3474           */
3475 3475          if ((FLAGS(dlmp) & FLG_RT_DELETE) &&
3476 3476              ((FLAGS(clmp) & FLG_RT_DELETE) == 0))
3477 3477                  return (0);
3478 3478  
3479 3479          /*
3480 3480           * An object with world access can always bind to an object with global
3481 3481           * visibility.
3482 3482           */
3483 3483          if (((MODE(clmp) & RTLD_WORLD) || (slflags & LKUP_WORLD)) &&
3484 3484              (MODE(dlmp) & RTLD_GLOBAL))
3485 3485                  return (1);
3486 3486  
3487 3487          /*
3488 3488           * An object with local access can only bind to an object that is a
3489 3489           * member of the same group.
3490 3490           */
3491 3491          if (((MODE(clmp) & RTLD_GROUP) == 0) ||
3492 3492              ((calp = GROUPS(clmp)) == NULL) || ((dalp = GROUPS(dlmp)) == NULL))
3493 3493                  return (0);
3494 3494  
3495 3495          /*
3496 3496           * Traverse the list of groups the caller is a part of.
3497 3497           */
3498 3498          for (APLIST_TRAVERSE(calp, idx1, ghp1)) {
3499 3499                  /*
3500 3500                   * If we're testing for the ability of two objects to bind to
3501 3501                   * each other regardless of a specific group, ignore that group.
3502 3502                   */
3503 3503                  if (ghp && (ghp1 == ghp))
3504 3504                          continue;
3505 3505  
3506 3506                  /*
3507 3507                   * Traverse the list of groups the destination is a part of.
3508 3508                   */
3509 3509                  for (APLIST_TRAVERSE(dalp, idx2, ghp2)) {
3510 3510                          Grp_desc        *gdp;
3511 3511                          Aliste          idx3;
3512 3512  
3513 3513                          if (ghp1 != ghp2)
3514 3514                                  continue;
3515 3515  
3516 3516                          /*
3517 3517                           * Make sure the relationship between the destination
3518 3518                           * and the caller provide symbols for relocation.
3519 3519                           * Parents are maintained as callers, but unless the
3520 3520                           * destination object was opened with RTLD_PARENT, the
3521 3521                           * parent doesn't provide symbols for the destination
3522 3522                           * to relocate against.
3523 3523                           */
3524 3524                          for (ALIST_TRAVERSE(ghp2->gh_depends, idx3, gdp)) {
3525 3525                                  if (dlmp != gdp->gd_depend)
3526 3526                                          continue;
3527 3527  
3528 3528                                  if (gdp->gd_flags & GPD_RELOC)
3529 3529                                          return (1);
3530 3530                          }
3531 3531                  }
3532 3532          }
3533 3533          return (0);
3534 3534  }
3535 3535  
3536 3536  /*
3537 3537   * Initialize the environ symbol.  Traditionally this is carried out by the crt
3538 3538   * code prior to jumping to main.  However, init sections get fired before this
3539 3539   * variable is initialized, so ld.so.1 sets this directly from the AUX vector
3540 3540   * information.  In addition, a process may have multiple link-maps (ld.so.1's
3541 3541   * debugging and preloading objects), and link auditing, and each may need an
3542 3542   * environ variable set.
3543 3543   *
3544 3544   * This routine is called after a relocation() pass, and thus provides for:
3545 3545   *
3546 3546   *  -   setting environ on the main link-map after the initial application and
3547 3547   *      its dependencies have been established.  Typically environ lives in the
3548 3548   *      application (provided by its crt), but in older applications it might
3549 3549   *      be in libc.  Who knows what's expected of applications not built on
3550 3550   *      Solaris.
3551 3551   *
3552 3552   *  -   after loading a new shared object.  We can add shared objects to various
3553 3553   *      link-maps, and any link-map dependencies requiring getopt() require
3554 3554   *      their own environ.  In addition, lazy loading might bring in the
3555 3555   *      supplier of environ (libc used to be a lazy loading candidate) after
3556 3556   *      the link-map has been established and other objects are present.
3557 3557   *
3558 3558   * This routine handles all these scenarios, without adding unnecessary overhead
3559 3559   * to ld.so.1.
3560 3560   */
3561 3561  void
3562 3562  set_environ(Lm_list *lml)
3563 3563  {
3564 3564          Slookup         sl;
3565 3565          Sresult         sr;
3566 3566          uint_t          binfo;
3567 3567  
3568 3568          /*
3569 3569           * Initialize the symbol lookup, and symbol result, data structures.
3570 3570           */
3571 3571          SLOOKUP_INIT(sl, MSG_ORIG(MSG_SYM_ENVIRON), lml->lm_head, lml->lm_head,
3572 3572              ld_entry_cnt, 0, 0, 0, 0, LKUP_WEAK);
3573 3573          SRESULT_INIT(sr, MSG_ORIG(MSG_SYM_ENVIRON));
3574 3574  
3575 3575          if (LM_LOOKUP_SYM(lml->lm_head)(&sl, &sr, &binfo, 0)) {
3576 3576                  Rt_map  *dlmp = sr.sr_dmap;
3577 3577  
3578 3578                  lml->lm_environ = (char ***)sr.sr_sym->st_value;
3579 3579  
3580 3580                  if (!(FLAGS(dlmp) & FLG_RT_FIXED))
3581 3581                          lml->lm_environ =
3582 3582                              (char ***)((uintptr_t)lml->lm_environ +
3583 3583                              (uintptr_t)ADDR(dlmp));
3584 3584                  *(lml->lm_environ) = (char **)environ;
3585 3585                  lml->lm_flags |= LML_FLG_ENVIRON;
3586 3586          }
3587 3587  }
3588 3588  
3589 3589  /*
3590 3590   * Determine whether we have a secure executable.  Uid and gid information
3591 3591   * can be passed to us via the aux vector, however if these values are -1
3592 3592   * then use the appropriate system call to obtain them.
3593 3593   *
3594 3594   *  -   If the user is the root they can do anything
3595 3595   *
3596 3596   *  -   If the real and effective uid's don't match, or the real and
3597 3597   *      effective gid's don't match then this is determined to be a `secure'
3598 3598   *      application.
3599 3599   *
3600 3600   * This function is called prior to any dependency processing (see _setup.c).
3601 3601   * Any secure setting will remain in effect for the life of the process.
3602 3602   */
3603 3603  void
3604 3604  security(uid_t uid, uid_t euid, gid_t gid, gid_t egid, int auxflags)
3605 3605  {
3606 3606          if (auxflags != -1) {
3607 3607                  if ((auxflags & AF_SUN_SETUGID) != 0)
3608 3608                          rtld_flags |= RT_FL_SECURE;
3609 3609                  return;
3610 3610          }
3611 3611  
3612 3612          if (uid == (uid_t)-1)
3613 3613                  uid = getuid();
3614 3614          if (uid) {
3615 3615                  if (euid == (uid_t)-1)
3616 3616                          euid = geteuid();
3617 3617                  if (uid != euid)
3618 3618                          rtld_flags |= RT_FL_SECURE;
3619 3619                  else {
3620 3620                          if (gid == (gid_t)-1)
3621 3621                                  gid = getgid();
3622 3622                          if (egid == (gid_t)-1)
3623 3623                                  egid = getegid();
3624 3624                          if (gid != egid)
3625 3625                                  rtld_flags |= RT_FL_SECURE;
3626 3626                  }
3627 3627          }
3628 3628  }
3629 3629  
3630 3630  /*
3631 3631   * Determine whether ld.so.1 itself is owned by root and has its mode setuid.
3632 3632   */
3633 3633  int
3634 3634  is_rtld_setuid()
3635 3635  {
3636 3636          rtld_stat_t     status;
3637 3637          const char      *name;
3638 3638  
3639 3639          if (rtld_flags2 & RT_FL2_SETUID)
3640 3640                  return (1);
3641 3641  
3642 3642          if (interp && interp->i_name)
3643 3643                  name = interp->i_name;
3644 3644          else
3645 3645                  name = NAME(lml_rtld.lm_head);
3646 3646  
3647 3647          if (((rtld_stat(name, &status) == 0) &&
3648 3648              (status.st_uid == 0) && (status.st_mode & S_ISUID))) {
3649 3649                  rtld_flags2 |= RT_FL2_SETUID;
3650 3650                  return (1);
3651 3651          }
3652 3652          return (0);
3653 3653  }
3654 3654  
3655 3655  /*
3656 3656   * Determine that systems platform name.  Normally, this name is provided from
3657 3657   * the AT_SUN_PLATFORM aux vector from the kernel.  This routine provides a
3658 3658   * fall back.
3659 3659   */
3660 3660  void
3661 3661  platform_name(Syscapset *scapset)
3662 3662  {
3663 3663          char    info[SYS_NMLN];
3664 3664          size_t  size;
3665 3665  
3666 3666          if ((scapset->sc_platsz = size =
3667 3667              sysinfo(SI_PLATFORM, info, SYS_NMLN)) == (size_t)-1)
3668 3668                  return;
3669 3669  
3670 3670          if ((scapset->sc_plat = malloc(size)) == NULL) {
3671 3671                  scapset->sc_platsz = (size_t)-1;
3672 3672                  return;
3673 3673          }
3674 3674          (void) strcpy(scapset->sc_plat, info);
3675 3675  }
3676 3676  
3677 3677  /*
3678 3678   * Determine that systems machine name.  Normally, this name is provided from
3679 3679   * the AT_SUN_MACHINE aux vector from the kernel.  This routine provides a
3680 3680   * fall back.
3681 3681   */
3682 3682  void
3683 3683  machine_name(Syscapset *scapset)
3684 3684  {
3685 3685          char    info[SYS_NMLN];
3686 3686          size_t  size;
3687 3687  
3688 3688          if ((scapset->sc_machsz = size =
3689 3689              sysinfo(SI_MACHINE, info, SYS_NMLN)) == (size_t)-1)
3690 3690                  return;
3691 3691  
3692 3692          if ((scapset->sc_mach = malloc(size)) == NULL) {
3693 3693                  scapset->sc_machsz = (size_t)-1;
3694 3694                  return;
3695 3695          }
3696 3696          (void) strcpy(scapset->sc_mach, info);
3697 3697  }
3698 3698  
3699 3699  /*
3700 3700   * _REENTRANT code gets errno redefined to a function so provide for return
3701 3701   * of the thread errno if applicable.  This has no meaning in ld.so.1 which
3702 3702   * is basically singled threaded.  Provide the interface for our dependencies.
3703 3703   */
3704 3704  #undef errno
3705 3705  int *
3706 3706  ___errno()
3707 3707  {
3708 3708          extern  int     errno;
3709 3709  
3710 3710          return (&errno);
3711 3711  }
3712 3712  
3713 3713  /*
3714 3714   * Determine whether a symbol name should be demangled.
3715 3715   */
3716 3716  const char *
3717 3717  demangle(const char *name)
3718 3718  {
3719 3719          if (rtld_flags & RT_FL_DEMANGLE)
3720 3720                  return (conv_demangle_name(name));
3721 3721          else
3722 3722                  return (name);
3723 3723  }
3724 3724  
3725 3725  #ifndef _LP64
3726 3726  /*
3727 3727   * Wrappers on stat() and fstat() for 32-bit rtld that uses stat64()
3728 3728   * underneath while preserving the object size limits of a non-largefile
3729 3729   * enabled 32-bit process. The purpose of this is to prevent large inode
3730 3730   * values from causing stat() to fail.
3731 3731   */
3732 3732  inline static int
3733 3733  rtld_stat_process(int r, struct stat64 *lbuf, rtld_stat_t *restrict buf)
3734 3734  {
3735 3735          extern int      errno;
3736 3736  
3737 3737          /*
3738 3738           * Although we used a 64-bit capable stat(), the 32-bit rtld
3739 3739           * can only handle objects < 2GB in size. If this object is
3740 3740           * too big, turn the success into an overflow error.
3741 3741           */
3742 3742          if ((lbuf->st_size & 0xffffffff80000000) != 0) {
3743 3743                  errno = EOVERFLOW;
3744 3744                  return (-1);
3745 3745          }
3746 3746  
3747 3747          /*
3748 3748           * Transfer the information needed by rtld into a rtld_stat_t
3749 3749           * structure that preserves the non-largile types for everything
3750 3750           * except inode.
3751 3751           */
3752 3752          buf->st_dev = lbuf->st_dev;
3753 3753          buf->st_ino = lbuf->st_ino;
3754 3754          buf->st_mode = lbuf->st_mode;
3755 3755          buf->st_uid = lbuf->st_uid;
3756 3756          buf->st_size = (off_t)lbuf->st_size;
3757 3757          buf->st_mtim = lbuf->st_mtim;
3758 3758  #ifdef sparc
3759 3759          buf->st_blksize = lbuf->st_blksize;
3760 3760  #endif
3761 3761  
3762 3762          return (r);
3763 3763  }
3764 3764  
3765 3765  int
3766 3766  rtld_stat(const char *restrict path, rtld_stat_t *restrict buf)
3767 3767  {
3768 3768          struct stat64   lbuf;
3769 3769          int             r;
3770 3770  
3771 3771          r = stat64(path, &lbuf);
3772 3772          if (r != -1)
3773 3773                  r = rtld_stat_process(r, &lbuf, buf);
3774 3774          return (r);
3775 3775  }
3776 3776  
3777 3777  int
3778 3778  rtld_fstat(int fildes, rtld_stat_t *restrict buf)
3779 3779  {
3780 3780          struct stat64   lbuf;
3781 3781          int             r;
3782 3782  
3783 3783          r = fstat64(fildes, &lbuf);
3784 3784          if (r != -1)
3785 3785                  r = rtld_stat_process(r, &lbuf, buf);
3786 3786          return (r);
3787 3787  }
3788 3788  #endif
  
    | ↓ open down ↓ | 649 lines elided | ↑ open up ↑ | 
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX