1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  *      Copyright (c) 1988 AT&T
  24  *        All Rights Reserved
  25  *
  26  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  27  */
  28 
  29 #include        <sys/types.h>
  30 #include        <sys/mman.h>
  31 #include        <signal.h>
  32 #include        <dlfcn.h>
  33 #include        <synch.h>
  34 #include        <debug.h>
  35 #include        "_rtld.h"
  36 
  37 /*
  38  * Declarations of global variables used in ld.so.
  39  */
  40 Rt_lock         rtldlock;
  41 int             thr_flg_nolock = 0;
  42 int             thr_flg_reenter = 0;
  43 
  44 /*
  45  * Major link-map lists.
  46  */
  47 Lm_list         lml_main =      { 0 };          /* the `main's link map list */
  48 Lm_list         lml_rtld =      { 0 };          /* rtld's link map list */
  49 
  50 /*
  51  * Entrance count.  Each time ld.so.1 is entered following initial process
  52  * setup, this count is bumped.  This value serves to identify the present
  53  * ld.so.1 operation.
  54  *
  55  * An ld.so.1 operation can result in many symbol lookup requests (i.e., loading
  56  * objects and relocating all symbolic bindings).  This count is used to protect
  57  * against attempting to re-load a failed lazy load within a single call to
  58  * ld.so.1, while allowing such attempts across calls.  Should a lazy load fail,
  59  * the present operation identifier is saved in the current symbol lookup data
  60  * block (Slookup).  Should a lazy load fall back operation be triggered, the
  61  * identifier in the symbol lookup block is compared to the current ld.so.1
  62  * entry count, and if the two are equal the fall back is skipped.
  63  *
  64  * With this count, there is a danger of wrap-around, although as an unsigned
  65  * 32-bit value, it is highly unlikely that any application could usefully make
  66  * 4.3 giga-calls into ld.so.1.  The worst that can occur is that a fall back
  67  * lazy load isn't triggered.  However, most lazy loads that fail typically
  68  * continue to fail unless the user takes corrective action (adds the necessary
  69  * (fixed) dependencies to the system).
  70  */
  71 ulong_t         ld_entry_cnt = 1;
  72 
  73 /*
  74  * BEGIN: Exposed to rtld_db, don't change without a coordinated handshake with
  75  * librtld_db (remembering that librtld_db must be able to read old as well as
  76  * current core files).
  77  */
  78 APlist          *dynlm_list = NULL;     /* dynamic list of link-maps */
  79 /*
  80  * END: Exposed to rtld_db
  81  */
  82 
  83 Reglist         *reglist = NULL;        /* list of register symbols */
  84 
  85 /*
  86  * Set of integers to track how many of what type of PLT's have been bound.
  87  * This is only really interesting for SPARC since ia32 has only one PLT.
  88  */
  89 uint32_t        pltcnt21d = 0;
  90 uint32_t        pltcnt24d = 0;
  91 uint32_t        pltcntu32 = 0;
  92 uint32_t        pltcntu44 = 0;
  93 uint32_t        pltcntfull = 0;
  94 uint32_t        pltcntfar = 0;
  95 
  96 /*
  97  * AVL tree pointers.
  98  */
  99 avl_tree_t      *capavl = NULL;         /* capabilities files */
 100 avl_tree_t      *nfavl = NULL;          /* not-found path names */
 101 avl_tree_t      *spavl = NULL;          /* secure path names */
 102 
 103 /*
 104  * Various other global data.
 105  */
 106 uint_t          rtld_flags = 0;
 107 uint_t          rtld_flags2 = 0;
 108 
 109 Lc_desc         glcs[CI_MAX];           /* global external interfaces */
 110 
 111 const char      *procname = NULL;
 112 const char      *rtldname = MSG_ORIG(MSG_FIL_RTLD);
 113 
 114 char            *lasterr = NULL;        /* string describing last error */
 115                                         /*    cleared by each dlerror() */
 116 Interp          *interp = NULL;         /* ELF interpreter info */
 117 APlist          *hdl_alp[HDLIST_SZ+2];  /* dlopen() handle list */
 118 size_t          syspagsz = 0;           /* system page size */
 119 ulong_t         at_flags = 0;           /* machine specific file flags */
 120 Uts_desc        *uts = NULL;            /* utsname descriptor */
 121 Isa_desc        *isa = NULL;            /* isalist descriptor */
 122 
 123 uint_t          audit_argcnt = 64;      /* no. of stack args to copy (default */
 124                                         /*    is all) */
 125 Audit_desc      *auditors = NULL;       /* global auditors (LD_AUDIT) */
 126 APlist          *aud_preinit = NULL;    /* list of objects defining local */
 127 APlist          *aud_activity = NULL;   /*    preinit and activity auditors */
 128 
 129 const char      *rpl_audit = NULL;      /* replaceable LD_AUDIT string */
 130 const char      *rpl_debug = NULL;      /* replaceable LD_DEBUG string */
 131 const char      *rpl_ldflags = NULL;    /* replaceable LD_FLAGS string */
 132 const char      *rpl_libpath = NULL;    /* replaceable LD_LIBRARY_PATH string */
 133 Alist           *rpl_libdirs = NULL;    /*    and associated Pdesc list */
 134 const char      *rpl_preload = NULL;    /* replaceable LD_PRELOAD string */
 135 
 136 const char      *prm_audit = NULL;      /* permanent LD_AUDIT string */
 137 const char      *prm_debug = NULL;      /* permanent LD_DEBUG string */
 138 const char      *prm_ldflags = NULL;    /* permanent LD_FLAGS string */
 139 const char      *prm_libpath = NULL;    /* permanent LD_LIBRARY_PATH string */
 140 Alist           *prm_libdirs = NULL;    /*    and associated Pdesc list */
 141 const char      *prm_preload = NULL;    /* permanent LD_PRELOAD string */
 142 
 143 uint_t          env_info = 0;           /* information regarding environment */
 144                                         /*    variables */
 145 int             killsig = SIGKILL;      /* signal sent on fatal exit */
 146 APlist          *free_alp = NULL;       /* defragmentation list */
 147 
 148 /*
 149  * Capabilities are provided by the system.  However, users can define an
 150  * alternative set of system capabilities, where they can add, subtract, or
 151  * override the system capabilities for testing purposes.  Furthermore, these
 152  * alternative capabilities can be specified such that they only apply to
 153  * specified files rather than to all objects.
 154  *
 155  * The org_scapset is relied upon by the amd64 version of elf_rtbndr to
 156  * determine whether or not AVX registers are present in the system.
 157  */
 158 static Syscapset        scapset = { 0 };
 159 Syscapset       *org_scapset = &scapset;    /* original system and */
 160 Syscapset       *alt_scapset = &scapset;    /* alternative system */
 161                                                 /*      capabilities */
 162 
 163 const char      *rpl_hwcap = NULL;      /* replaceable hwcap str */
 164 const char      *rpl_sfcap = NULL;      /* replaceable sfcap str */
 165 const char      *rpl_machcap = NULL;    /* replaceable machcap str */
 166 const char      *rpl_platcap = NULL;    /* replaceable platcap str */
 167 const char      *rpl_cap_files = NULL;  /* associated files */
 168 
 169 const char      *prm_hwcap = NULL;      /* permanent hwcap str */
 170 const char      *prm_sfcap = NULL;      /* permanent sfcap str */
 171 const char      *prm_machcap = NULL;    /* permanent machcap str */
 172 const char      *prm_platcap = NULL;    /* permanent platcap str */
 173 const char      *prm_cap_files = NULL;  /* associated files */
 174 
 175 /*
 176  * Note, the debugging descriptor interposes on the default definition provided
 177  * by liblddbg.  This is required as ld.so.1 must only have outstanding relative
 178  * relocations.
 179  */
 180 static Dbg_desc _dbg_desc = {0, 0, 0};
 181 Dbg_desc        *dbg_desc = &_dbg_desc;     /* debugging descriptor */
 182 const char      *dbg_file = NULL;       /* debugging directed to file */
 183 
 184 #pragma weak    environ = _environ      /* environ for PLT tracing - we */
 185 char            **_environ = NULL;      /* supply the pair to satisfy any */
 186                                         /* libc requirements (hwmuldiv) */
 187 
 188 const char      *profile_name = NULL;   /* object being profiled */
 189 const char      *profile_out = NULL;    /* profile output file */
 190 const char      *profile_lib = NULL;    /* audit library to perform profile */
 191 
 192 uchar_t         search_rules[] = {      /* dependency search rules */
 193                 RPLENV,                 /*      replaceable LD_LIBRARY_PATH */
 194                 PRMENV,                 /*      permanent LD_LIBRARY_PATH */
 195                 RUNPATH,                /*      callers runpath */
 196                 DEFAULT,                /*      default library path */
 197                 0
 198 };
 199 
 200 Dl_argsinfo     argsinfo = { 0 };       /* process argument, environment and */
 201                                         /*      auxv information. */
 202 
 203 /*
 204  * Frequently used messages are cached here to reduce _dgettext() overhead and
 205  * also provide for resetting should the locale change (see _ld_libc()).
 206  */
 207 const char      *err_strs[ERR_NUM] = { NULL };
 208 const char      *nosym_str = NULL;
 209 
 210 
 211 /*
 212  * Rejection error message tables.
 213  */
 214 const Msg
 215 ldd_reject[SGS_REJ_NUM] = {
 216                 MSG_STR_EMPTY,
 217                 MSG_LDD_REJ_MACH,       /* MSG_INTL(MSG_LDD_REJ_MACH) */
 218                 MSG_LDD_REJ_CLASS,      /* MSG_INTL(MSG_LDD_REJ_CLASS) */
 219                 MSG_LDD_REJ_DATA,       /* MSG_INTL(MSG_LDD_REJ_DATA) */
 220                 MSG_LDD_REJ_TYPE,       /* MSG_INTL(MSG_LDD_REJ_TYPE) */
 221                 MSG_LDD_REJ_BADFLAG,    /* MSG_INTL(MSG_LDD_REJ_BADFLAG) */
 222                 MSG_LDD_REJ_MISFLAG,    /* MSG_INTL(MSG_LDD_REJ_MISFLAG) */
 223                 MSG_LDD_REJ_VERSION,    /* MSG_INTL(MSG_LDD_REJ_VERSION) */
 224                 MSG_LDD_REJ_HAL,        /* MSG_INTL(MSG_LDD_REJ_HAL) */
 225                 MSG_LDD_REJ_US3,        /* MSG_INTL(MSG_LDD_REJ_US3) */
 226                 MSG_LDD_REJ_STR,        /* MSG_INTL(MSG_LDD_REJ_STR) */
 227                 MSG_LDD_REJ_UNKFILE,    /* MSG_INTL(MSG_LDD_REJ_UNKFILE) */
 228                 MSG_LDD_REJ_UNKCAP,     /* MSG_INTL(MSG_LDD_REJ_UNKCAP) */
 229                 MSG_LDD_REJ_HWCAP_1,    /* MSG_INTL(MSG_LDD_REJ_HWCAP_1) */
 230                 MSG_LDD_REJ_SFCAP_1,    /* MSG_INTL(MSG_LDD_REJ_SFCAP_1) */
 231                 MSG_LDD_REJ_MACHCAP,    /* MSG_INTL(MSG_LDD_REJ_MACHCAP) */
 232                 MSG_LDD_REJ_PLATCAP,    /* MSG_INTL(MSG_LDD_REJ_PLATCAP) */
 233                 MSG_LDD_REJ_HWCAP_2,    /* MSG_INTL(MSG_LDD_REJ_HWCAP_2) */
 234                 MSG_LDD_REJ_ARCHIVE     /* MSG_INTL(MSG_LDD_REJ_ARCHIVE) */
 235         };
 236 #if SGS_REJ_NUM != (SGS_REJ_ARCHIVE + 1)
 237 #error SGS_REJ_NUM has changed
 238 #endif
 239 
 240 const Msg
 241 err_reject[SGS_REJ_NUM] = {
 242                 MSG_STR_EMPTY,
 243                 MSG_ERR_REJ_MACH,       /* MSG_INTL(MSG_ERR_REJ_MACH) */
 244                 MSG_ERR_REJ_CLASS,      /* MSG_INTL(MSG_ERR_REJ_CLASS) */
 245                 MSG_ERR_REJ_DATA,       /* MSG_INTL(MSG_ERR_REJ_DATA) */
 246                 MSG_ERR_REJ_TYPE,       /* MSG_INTL(MSG_ERR_REJ_TYPE) */
 247                 MSG_ERR_REJ_BADFLAG,    /* MSG_INTL(MSG_ERR_REJ_BADFLAG) */
 248                 MSG_ERR_REJ_MISFLAG,    /* MSG_INTL(MSG_ERR_REJ_MISFLAG) */
 249                 MSG_ERR_REJ_VERSION,    /* MSG_INTL(MSG_ERR_REJ_VERSION) */
 250                 MSG_ERR_REJ_HAL,        /* MSG_INTL(MSG_ERR_REJ_HAL) */
 251                 MSG_ERR_REJ_US3,        /* MSG_INTL(MSG_ERR_REJ_US3) */
 252                 MSG_ERR_REJ_STR,        /* MSG_INTL(MSG_ERR_REJ_STR) */
 253                 MSG_ERR_REJ_UNKFILE,    /* MSG_INTL(MSG_ERR_REJ_UNKFILE) */
 254                 MSG_ERR_REJ_UNKCAP,     /* MSG_INTL(MSG_ERR_REJ_UNKCAP) */
 255                 MSG_ERR_REJ_HWCAP_1,    /* MSG_INTL(MSG_ERR_REJ_HWCAP_1) */
 256                 MSG_ERR_REJ_SFCAP_1,    /* MSG_INTL(MSG_ERR_REJ_SFCAP_1) */
 257                 MSG_ERR_REJ_MACHCAP,    /* MSG_INTL(MSG_ERR_REJ_MACHCAP) */
 258                 MSG_ERR_REJ_PLATCAP,    /* MSG_INTL(MSG_ERR_REJ_PLATCAP) */
 259                 MSG_ERR_REJ_HWCAP_2,    /* MSG_INTL(MSG_ERR_REJ_HWCAP_2) */
 260                 MSG_ERR_REJ_ARCHIVE,    /* MSG_INTL(MSG_ERR_REJ_ARCHIVE) */
 261         };
 262 #if SGS_REJ_NUM != (SGS_REJ_ARCHIVE + 1)
 263 #error SGS_REJ_NUM has changed
 264 #endif
 265 
 266 const Msg
 267 ldd_warn[SGS_REJ_NUM] = {
 268                 MSG_STR_EMPTY,
 269                 MSG_STR_EMPTY,
 270                 MSG_STR_EMPTY,
 271                 MSG_STR_EMPTY,
 272                 MSG_STR_EMPTY,
 273                 MSG_STR_EMPTY,
 274                 MSG_STR_EMPTY,
 275                 MSG_STR_EMPTY,
 276                 MSG_STR_EMPTY,
 277                 MSG_STR_EMPTY,
 278                 MSG_STR_EMPTY,
 279                 MSG_STR_EMPTY,
 280                 MSG_LDD_WARN_UNKCAP,    /* MSG_INTL(MSG_LDD_WARN_UNKCAP) */
 281                 MSG_LDD_WARN_HWCAP_1,   /* MSG_INTL(MSG_LDD_WARN_HWCAP_1) */
 282                 MSG_LDD_WARN_SFCAP_1,   /* MSG_INTL(MSG_LDD_WARN_SFCAP_1) */
 283                 MSG_LDD_WARN_MACHCAP,   /* MSG_INTL(MSG_LDD_WARN_MACHCAP) */
 284                 MSG_LDD_WARN_PLATCAP,   /* MSG_INTL(MSG_LDD_WARN_PLATCAP) */
 285                 MSG_LDD_WARN_HWCAP_2,   /* MSG_INTL(MSG_LDD_WARN_HWCAP_2) */
 286                 MSG_STR_EMPTY
 287         };
 288 #if SGS_REJ_NUM != (SGS_REJ_ARCHIVE + 1)
 289 #error SGS_REJ_NUM has changed
 290 #endif