Back to index

glibc  2.9
dl-sysdep.c
Go to the documentation of this file.
00001 /* Operating system support for run-time dynamic linker.  Generic Unix version.
00002    Copyright (C) 1995-1998, 2000-2007, 2008 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <assert.h>
00021 #include <elf.h>
00022 #include <errno.h>
00023 #include <fcntl.h>
00024 #include <libintl.h>
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <unistd.h>
00028 #include <sys/types.h>
00029 #include <sys/stat.h>
00030 #include <sys/mman.h>
00031 #include <ldsodefs.h>
00032 #include <stdio-common/_itoa.h>
00033 #include <fpu_control.h>
00034 
00035 #include <entry.h>
00036 #include <dl-machine.h>
00037 #include <dl-procinfo.h>
00038 #include <dl-osinfo.h>
00039 #include <hp-timing.h>
00040 #include <tls.h>
00041 
00042 #ifdef _DL_FIRST_PLATFORM
00043 # define _DL_FIRST_EXTRA (_DL_FIRST_PLATFORM + _DL_PLATFORMS_COUNT)
00044 #else
00045 # define _DL_FIRST_EXTRA _DL_HWCAP_COUNT
00046 #endif
00047 
00048 extern char **_environ attribute_hidden;
00049 extern void _end attribute_hidden;
00050 
00051 /* Protect SUID program against misuse of file descriptors.  */
00052 extern void __libc_check_standard_fds (void);
00053 
00054 #ifdef NEED_DL_BASE_ADDR
00055 ElfW(Addr) _dl_base_addr;
00056 #endif
00057 int __libc_enable_secure attribute_relro = 0;
00058 INTVARDEF(__libc_enable_secure)
00059 int __libc_multiple_libcs = 0;     /* Defining this here avoids the inclusion
00060                                of init-first.  */
00061 /* This variable contains the lowest stack address ever used.  */
00062 void *__libc_stack_end attribute_relro = NULL;
00063 rtld_hidden_data_def(__libc_stack_end)
00064 static ElfW(auxv_t) *_dl_auxv attribute_relro;
00065 
00066 #ifndef DL_FIND_ARG_COMPONENTS
00067 # define DL_FIND_ARG_COMPONENTS(cookie, argc, argv, envp, auxp)       \
00068   do {                                                               \
00069     void **_tmp;                                                     \
00070     (argc) = *(long int *) cookie;                                   \
00071     (argv) = (char **) ((long int *) cookie + 1);                           \
00072     (envp) = (argv) + (argc) + 1;                                    \
00073     for (_tmp = (void **) (envp); *_tmp; ++_tmp)                     \
00074       continue;                                                             \
00075     (auxp) = (void *) ++_tmp;                                               \
00076   } while (0)
00077 #endif
00078 
00079 #ifndef DL_STACK_END
00080 # define DL_STACK_END(cookie) ((void *) (cookie))
00081 #endif
00082 
00083 ElfW(Addr)
00084 _dl_sysdep_start (void **start_argptr,
00085                 void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
00086                                ElfW(Addr) *user_entry))
00087 {
00088   const ElfW(Phdr) *phdr = NULL;
00089   ElfW(Word) phnum = 0;
00090   ElfW(Addr) user_entry;
00091   ElfW(auxv_t) *av;
00092 #ifdef HAVE_AUX_SECURE
00093 # define set_seen(tag) (tag)       /* Evaluate for the side effects.  */
00094 # define set_seen_secure() ((void) 0)
00095 #else
00096   uid_t uid = 0;
00097   gid_t gid = 0;
00098   unsigned int seen = 0;
00099 # define set_seen_secure() (seen = -1)
00100 # ifdef HAVE_AUX_XID
00101 #  define set_seen(tag) (tag)      /* Evaluate for the side effects.  */
00102 # else
00103 #  define M(type) (1 << (type))
00104 #  define set_seen(tag) seen |= M ((tag)->a_type)
00105 # endif
00106 #endif
00107 #ifdef NEED_DL_SYSINFO
00108   uintptr_t new_sysinfo = 0;
00109 #endif
00110 
00111   __libc_stack_end = DL_STACK_END (start_argptr);
00112   DL_FIND_ARG_COMPONENTS (start_argptr, _dl_argc, INTUSE(_dl_argv), _environ,
00113                        _dl_auxv);
00114 
00115   user_entry = (ElfW(Addr)) ENTRY_POINT;
00116   GLRO(dl_platform) = NULL; /* Default to nothing known about the platform.  */
00117 
00118   for (av = _dl_auxv; av->a_type != AT_NULL; set_seen (av++))
00119     switch (av->a_type)
00120       {
00121       case AT_PHDR:
00122        phdr = (void *) av->a_un.a_val;
00123        break;
00124       case AT_PHNUM:
00125        phnum = av->a_un.a_val;
00126        break;
00127       case AT_PAGESZ:
00128        GLRO(dl_pagesize) = av->a_un.a_val;
00129        break;
00130       case AT_ENTRY:
00131        user_entry = av->a_un.a_val;
00132        break;
00133 #ifdef NEED_DL_BASE_ADDR
00134       case AT_BASE:
00135        _dl_base_addr = av->a_un.a_val;
00136        break;
00137 #endif
00138 #ifndef HAVE_AUX_SECURE
00139       case AT_UID:
00140       case AT_EUID:
00141        uid ^= av->a_un.a_val;
00142        break;
00143       case AT_GID:
00144       case AT_EGID:
00145        gid ^= av->a_un.a_val;
00146        break;
00147 #endif
00148       case AT_SECURE:
00149 #ifndef HAVE_AUX_SECURE
00150        seen = -1;
00151 #endif
00152        INTUSE(__libc_enable_secure) = av->a_un.a_val;
00153        break;
00154       case AT_PLATFORM:
00155        GLRO(dl_platform) = (void *) av->a_un.a_val;
00156        break;
00157       case AT_HWCAP:
00158        GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
00159        break;
00160       case AT_CLKTCK:
00161        GLRO(dl_clktck) = av->a_un.a_val;
00162        break;
00163       case AT_FPUCW:
00164        GLRO(dl_fpu_control) = av->a_un.a_val;
00165        break;
00166 #ifdef NEED_DL_SYSINFO
00167       case AT_SYSINFO:
00168        new_sysinfo = av->a_un.a_val;
00169        break;
00170 #endif
00171 #if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
00172       case AT_SYSINFO_EHDR:
00173        GLRO(dl_sysinfo_dso) = (void *) av->a_un.a_val;
00174        break;
00175 #endif
00176 #ifdef DL_PLATFORM_AUXV
00177       DL_PLATFORM_AUXV
00178 #endif
00179       }
00180 
00181 #ifndef HAVE_AUX_SECURE
00182   if (seen != -1)
00183     {
00184       /* Fill in the values we have not gotten from the kernel through the
00185         auxiliary vector.  */
00186 # ifndef HAVE_AUX_XID
00187 #  define SEE(UID, var, uid) \
00188    if ((seen & M (AT_##UID)) == 0) var ^= __get##uid ()
00189       SEE (UID, uid, uid);
00190       SEE (EUID, uid, euid);
00191       SEE (GID, gid, gid);
00192       SEE (EGID, gid, egid);
00193 # endif
00194 
00195       /* If one of the two pairs of IDs does not match this is a setuid
00196         or setgid run.  */
00197       INTUSE(__libc_enable_secure) = uid | gid;
00198     }
00199 #endif
00200 
00201 #ifndef HAVE_AUX_PAGESIZE
00202   if (GLRO(dl_pagesize) == 0)
00203     GLRO(dl_pagesize) = __getpagesize ();
00204 #endif
00205 
00206 #if defined NEED_DL_SYSINFO
00207   /* Only set the sysinfo value if we also have the vsyscall DSO.  */
00208   if (GLRO(dl_sysinfo_dso) != 0 && new_sysinfo)
00209     GLRO(dl_sysinfo) = new_sysinfo;
00210 #endif
00211 
00212 #ifdef DL_SYSDEP_INIT
00213   DL_SYSDEP_INIT;
00214 #endif
00215 
00216 #ifdef DL_PLATFORM_INIT
00217   DL_PLATFORM_INIT;
00218 #endif
00219 
00220   /* Determine the length of the platform name.  */
00221   if (GLRO(dl_platform) != NULL)
00222     GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
00223 
00224   if (__sbrk (0) == &_end)
00225     /* The dynamic linker was run as a program, and so the initial break
00226        starts just after our bss, at &_end.  The malloc in dl-minimal.c
00227        will consume the rest of this page, so tell the kernel to move the
00228        break up that far.  When the user program examines its break, it
00229        will see this new value and not clobber our data.  */
00230     __sbrk (GLRO(dl_pagesize)
00231            - ((&_end - (void *) 0) & (GLRO(dl_pagesize) - 1)));
00232 
00233   /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
00234      allocated.  If necessary we are doing it ourself.  If it is not
00235      possible we stop the program.  */
00236   if (__builtin_expect (INTUSE(__libc_enable_secure), 0))
00237     __libc_check_standard_fds ();
00238 
00239   (*dl_main) (phdr, phnum, &user_entry);
00240   return user_entry;
00241 }
00242 
00243 void
00244 internal_function
00245 _dl_sysdep_start_cleanup (void)
00246 {
00247 }
00248 
00249 void
00250 internal_function
00251 _dl_show_auxv (void)
00252 {
00253   char buf[64];
00254   ElfW(auxv_t) *av;
00255 
00256   /* Terminate string.  */
00257   buf[63] = '\0';
00258 
00259   /* The following code assumes that the AT_* values are encoded
00260      starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
00261      close by (otherwise the array will be too large).  In case we have
00262      to support a platform where these requirements are not fulfilled
00263      some alternative implementation has to be used.  */
00264   for (av = _dl_auxv; av->a_type != AT_NULL; ++av)
00265     {
00266       static const struct
00267       {
00268        const char label[20];
00269        enum { unknown = 0, dec, hex, str, ignore } form;
00270       } auxvars[] =
00271        {
00272          [AT_EXECFD - 2] =         { "AT_EXECFD:       ", dec },
00273          [AT_EXECFN - 2] =         { "AT_EXECFN:       ", str },
00274          [AT_PHDR - 2] =           { "AT_PHDR:         0x", hex },
00275          [AT_PHENT - 2] =          { "AT_PHENT:        ", dec },
00276          [AT_PHNUM - 2] =          { "AT_PHNUM:        ", dec },
00277          [AT_PAGESZ - 2] =         { "AT_PAGESZ:       ", dec },
00278          [AT_BASE - 2] =           { "AT_BASE:         0x", hex },
00279          [AT_FLAGS - 2] =          { "AT_FLAGS:        0x", hex },
00280          [AT_ENTRY - 2] =          { "AT_ENTRY:        0x", hex },
00281          [AT_NOTELF - 2] =         { "AT_NOTELF:       ", hex },
00282          [AT_UID - 2] =            { "AT_UID:          ", dec },
00283          [AT_EUID - 2] =           { "AT_EUID:         ", dec },
00284          [AT_GID - 2] =            { "AT_GID:          ", dec },
00285          [AT_EGID - 2] =           { "AT_EGID:         ", dec },
00286          [AT_PLATFORM - 2] =              { "AT_PLATFORM:     ", str },
00287          [AT_HWCAP - 2] =          { "AT_HWCAP:        ", hex },
00288          [AT_CLKTCK - 2] =         { "AT_CLKTCK:       ", dec },
00289          [AT_FPUCW - 2] =          { "AT_FPUCW:        ", hex },
00290          [AT_DCACHEBSIZE - 2] =    { "AT_DCACHEBSIZE:  0x", hex },
00291          [AT_ICACHEBSIZE - 2] =    { "AT_ICACHEBSIZE:  0x", hex },
00292          [AT_UCACHEBSIZE - 2] =    { "AT_UCACHEBSIZE:  0x", hex },
00293          [AT_IGNOREPPC - 2] =             { "AT_IGNOREPPC", ignore },
00294          [AT_SECURE - 2] =         { "AT_SECURE:       ", dec },
00295          [AT_SYSINFO - 2] =        { "AT_SYSINFO:      0x", hex },
00296          [AT_SYSINFO_EHDR - 2] =   { "AT_SYSINFO_EHDR: 0x", hex },
00297        };
00298       unsigned int idx = (unsigned int) (av->a_type - 2);
00299 
00300       if ((unsigned int) av->a_type < 2u || auxvars[idx].form == ignore)
00301        continue;
00302 
00303       assert (AT_NULL == 0);
00304       assert (AT_IGNORE == 1);
00305 
00306       if (av->a_type == AT_HWCAP)
00307        {
00308          /* This is handled special.  */
00309          if (_dl_procinfo (av->a_un.a_val) == 0)
00310            continue;
00311        }
00312 
00313       if (idx < sizeof (auxvars) / sizeof (auxvars[0])
00314          && auxvars[idx].form != unknown)
00315        {
00316          const char *val = (char *) av->a_un.a_val;
00317 
00318          if (__builtin_expect (auxvars[idx].form, dec) == dec)
00319            val = _itoa ((unsigned long int) av->a_un.a_val,
00320                       buf + sizeof buf - 1, 10, 0);
00321          else if (__builtin_expect (auxvars[idx].form, hex) == hex)
00322            val = _itoa ((unsigned long int) av->a_un.a_val,
00323                       buf + sizeof buf - 1, 16, 0);
00324 
00325          _dl_printf ("%s%s\n", auxvars[idx].label, val);
00326 
00327          continue;
00328        }
00329 
00330       /* Unknown value: print a generic line.  */
00331       char buf2[17];
00332       buf[sizeof (buf2) - 1] = '\0';
00333       const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
00334                             buf2 + sizeof buf2 - 1, 16, 0);
00335       const char *val =  _itoa ((unsigned long int) av->a_type,
00336                             buf + sizeof buf - 1, 16, 0);
00337       _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
00338     }
00339 }
00340 
00341 
00342 /* Return an array of useful/necessary hardware capability names.  */
00343 const struct r_strlenpair *
00344 internal_function
00345 _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
00346                     size_t *max_capstrlen)
00347 {
00348   /* Determine how many important bits are set.  */
00349   uint64_t masked = GLRO(dl_hwcap) & GLRO(dl_hwcap_mask);
00350   size_t cnt = platform != NULL;
00351   size_t n, m;
00352   size_t total;
00353   struct r_strlenpair *temp;
00354   struct r_strlenpair *result;
00355   struct r_strlenpair *rp;
00356   char *cp;
00357 
00358   /* Count the number of bits set in the masked value.  */
00359   for (n = 0; (~((1ULL << n) - 1) & masked) != 0; ++n)
00360     if ((masked & (1ULL << n)) != 0)
00361       ++cnt;
00362 
00363 #if (defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO) && defined SHARED
00364   /* The system-supplied DSO can contain a note of type 2, vendor "GNU".
00365      This gives us a list of names to treat as fake hwcap bits.  */
00366 
00367   const char *dsocaps = NULL;
00368   size_t dsocapslen = 0;
00369   if (GLRO(dl_sysinfo_map) != NULL)
00370     {
00371       const ElfW(Phdr) *const phdr = GLRO(dl_sysinfo_map)->l_phdr;
00372       const ElfW(Word) phnum = GLRO(dl_sysinfo_map)->l_phnum;
00373       for (uint_fast16_t i = 0; i < phnum; ++i)
00374        if (phdr[i].p_type == PT_NOTE)
00375          {
00376            const ElfW(Addr) start = (phdr[i].p_vaddr
00377                                   + GLRO(dl_sysinfo_map)->l_addr);
00378            const struct
00379            {
00380              ElfW(Word) vendorlen;
00381              ElfW(Word) datalen;
00382              ElfW(Word) type;
00383            } *note = (const void *) start;
00384            while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
00385              {
00386 #define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
00387               if (note->type == 2
00388                   && note->vendorlen == sizeof "GNU"
00389                   && !memcmp ((note + 1), "GNU", sizeof "GNU")
00390                   && note->datalen > 2 * sizeof (ElfW(Word)) + 2)
00391                 {
00392                   const ElfW(Word) *p = ((const void *) (note + 1)
00393                                       + ROUND (sizeof "GNU"));
00394                   cnt += *p++;
00395                   ++p;      /* Skip mask word.  */
00396                   dsocaps = (const char *) p;
00397                   dsocapslen = note->datalen - sizeof *p * 2;
00398                   break;
00399                 }
00400               note = ((const void *) (note + 1)
00401                      + ROUND (note->vendorlen) + ROUND (note->datalen));
00402 #undef ROUND
00403              }
00404            if (dsocaps != NULL)
00405              break;
00406          }
00407     }
00408 #endif
00409 
00410   /* For TLS enabled builds always add 'tls'.  */
00411   ++cnt;
00412 
00413   /* Create temporary data structure to generate result table.  */
00414   temp = (struct r_strlenpair *) alloca (cnt * sizeof (*temp));
00415   m = 0;
00416 #if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
00417   if (dsocaps != NULL)
00418     {
00419       const ElfW(Word) mask = ((const ElfW(Word) *) dsocaps)[-1];
00420       GLRO(dl_hwcap) |= (uint64_t) mask << _DL_FIRST_EXTRA;
00421       size_t len;
00422       for (const char *p = dsocaps; p < dsocaps + dsocapslen; p += len + 1)
00423        {
00424          uint_fast8_t bit = *p++;
00425          len = strlen (p);
00426 
00427          /* Skip entries that are not enabled in the mask word.  */
00428          if (__builtin_expect (mask & ((ElfW(Word)) 1 << bit), 1))
00429            {
00430              temp[m].str = p;
00431              temp[m].len = len;
00432              ++m;
00433            }
00434          else
00435            --cnt;
00436        }
00437     }
00438 #endif
00439   for (n = 0; masked != 0; ++n)
00440     if ((masked & (1ULL << n)) != 0)
00441       {
00442        temp[m].str = _dl_hwcap_string (n);
00443        temp[m].len = strlen (temp[m].str);
00444        masked ^= 1ULL << n;
00445        ++m;
00446       }
00447   if (platform != NULL)
00448     {
00449       temp[m].str = platform;
00450       temp[m].len = platform_len;
00451       ++m;
00452     }
00453 
00454   temp[m].str = "tls";
00455   temp[m].len = 3;
00456   ++m;
00457 
00458   assert (m == cnt);
00459 
00460   /* Determine the total size of all strings together.  */
00461   if (cnt == 1)
00462     total = temp[0].len + 1;
00463   else
00464     {
00465       total = temp[0].len + temp[cnt - 1].len + 2;
00466       if (cnt > 2)
00467        {
00468          total <<= 1;
00469          for (n = 1; n + 1 < cnt; ++n)
00470            total += temp[n].len + 1;
00471          if (cnt > 3
00472              && (cnt >= sizeof (size_t) * 8
00473                 || total + (sizeof (*result) << 3)
00474                    >= (1UL << (sizeof (size_t) * 8 - cnt + 3))))
00475            _dl_signal_error (ENOMEM, NULL, NULL,
00476                            N_("cannot create capability list"));
00477 
00478          total <<= cnt - 3;
00479        }
00480     }
00481 
00482   /* The result structure: we use a very compressed way to store the
00483      various combinations of capability names.  */
00484   *sz = 1 << cnt;
00485   result = (struct r_strlenpair *) malloc (*sz * sizeof (*result) + total);
00486   if (result == NULL)
00487     _dl_signal_error (ENOMEM, NULL, NULL,
00488                     N_("cannot create capability list"));
00489 
00490   if (cnt == 1)
00491     {
00492       result[0].str = (char *) (result + *sz);
00493       result[0].len = temp[0].len + 1;
00494       result[1].str = (char *) (result + *sz);
00495       result[1].len = 0;
00496       cp = __mempcpy ((char *) (result + *sz), temp[0].str, temp[0].len);
00497       *cp = '/';
00498       *sz = 2;
00499       *max_capstrlen = result[0].len;
00500 
00501       return result;
00502     }
00503 
00504   /* Fill in the information.  This follows the following scheme
00505      (indeces from TEMP for four strings):
00506        entry #0: 0, 1, 2, 3 binary: 1111
00507              #1: 0, 1, 3            1101
00508              #2: 0, 2, 3            1011
00509              #3: 0, 3                      1001
00510      This allows the representation of all possible combinations of
00511      capability names in the string.  First generate the strings.  */
00512   result[1].str = result[0].str = cp = (char *) (result + *sz);
00513 #define add(idx) \
00514       cp = __mempcpy (__mempcpy (cp, temp[idx].str, temp[idx].len), "/", 1);
00515   if (cnt == 2)
00516     {
00517       add (1);
00518       add (0);
00519     }
00520   else
00521     {
00522       n = 1 << (cnt - 1);
00523       do
00524        {
00525          n -= 2;
00526 
00527          /* We always add the last string.  */
00528          add (cnt - 1);
00529 
00530          /* Add the strings which have the bit set in N.  */
00531          for (m = cnt - 2; m > 0; --m)
00532            if ((n & (1 << m)) != 0)
00533              add (m);
00534 
00535          /* Always add the first string.  */
00536          add (0);
00537        }
00538       while (n != 0);
00539     }
00540 #undef add
00541 
00542   /* Now we are ready to install the string pointers and length.  */
00543   for (n = 0; n < (1UL << cnt); ++n)
00544     result[n].len = 0;
00545   n = cnt;
00546   do
00547     {
00548       size_t mask = 1 << --n;
00549 
00550       rp = result;
00551       for (m = 1 << cnt; m > 0; ++rp)
00552        if ((--m & mask) != 0)
00553          rp->len += temp[n].len + 1;
00554     }
00555   while (n != 0);
00556 
00557   /* The first half of the strings all include the first string.  */
00558   n = (1 << cnt) - 2;
00559   rp = &result[2];
00560   while (n != (1UL << (cnt - 1)))
00561     {
00562       if ((--n & 1) != 0)
00563        rp[0].str = rp[-2].str + rp[-2].len;
00564       else
00565        rp[0].str = rp[-1].str;
00566       ++rp;
00567     }
00568 
00569   /* The second half starts right after the first part of the string of
00570      the corresponding entry in the first half.  */
00571   do
00572     {
00573       rp[0].str = rp[-(1 << (cnt - 1))].str + temp[cnt - 1].len + 1;
00574       ++rp;
00575     }
00576   while (--n != 0);
00577 
00578   /* The maximum string length.  */
00579   *max_capstrlen = result[0].len;
00580 
00581   return result;
00582 }