1  /* Dynamic linker system dependencies for Linux.
       2     Copyright (C) 1995-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <_itoa.h>
      20  #include <assert.h>
      21  #include <dl-auxv.h>
      22  #include <dl-osinfo.h>
      23  #include <dl-parse_auxv.h>
      24  #include <dl-procinfo.h>
      25  #include <dl-tunables.h>
      26  #include <elf.h>
      27  #include <errno.h>
      28  #include <fcntl.h>
      29  #include <ldsodefs.h>
      30  #include <libc-internal.h>
      31  #include <libintl.h>
      32  #include <not-cancel.h>
      33  #include <stdlib.h>
      34  #include <string.h>
      35  #include <string.h>
      36  #include <sys/mman.h>
      37  #include <sys/param.h>
      38  #include <sys/stat.h>
      39  #include <sys/types.h>
      40  #include <sys/utsname.h>
      41  #include <tls.h>
      42  #include <unistd.h>
      43  
      44  #include <dl-machine.h>
      45  #include <dl-hwcap-check.h>
      46  
      47  #ifdef SHARED
      48  extern char **_environ attribute_hidden;
      49  extern char _end[] attribute_hidden;
      50  
      51  /* Protect SUID program against misuse of file descriptors.  */
      52  extern void __libc_check_standard_fds (void);
      53  
      54  int __libc_enable_secure attribute_relro = 0;
      55  rtld_hidden_data_def (__libc_enable_secure)
      56  /* This variable contains the lowest stack address ever used.  */
      57  void *__libc_stack_end attribute_relro = NULL;
      58  rtld_hidden_data_def(__libc_stack_end)
      59  void *_dl_random attribute_relro = NULL;
      60  
      61  #ifndef DL_STACK_END
      62  # define DL_STACK_END(cookie) ((void *) (cookie))
      63  #endif
      64  
      65  /* Arguments passed to dl_main.  */
      66  struct dl_main_arguments
      67  {
      68    const ElfW(Phdr) *phdr;
      69    ElfW(Word) phnum;
      70    ElfW(Addr) user_entry;
      71  };
      72  
      73  /* Separate function, so that dl_main can be called without the large
      74     array on the stack.  */
      75  static void
      76  _dl_sysdep_parse_arguments (void **start_argptr,
      77  			    struct dl_main_arguments *args)
      78  {
      79    _dl_argc = (intptr_t) *start_argptr;
      80    _dl_argv = (char **) (start_argptr + 1); /* Necessary aliasing violation.  */
      81    _environ = _dl_argv + _dl_argc + 1;
      82    for (char **tmp = _environ; ; ++tmp)
      83      if (*tmp == NULL)
      84        {
      85  	/* Another necessary aliasing violation.  */
      86  	GLRO(dl_auxv) = (ElfW(auxv_t) *) (tmp + 1);
      87  	break;
      88        }
      89  
      90    dl_parse_auxv_t auxv_values = { 0, };
      91    _dl_parse_auxv (GLRO(dl_auxv), auxv_values);
      92  
      93    args->phdr = (const ElfW(Phdr) *) auxv_values[AT_PHDR];
      94    args->phnum = auxv_values[AT_PHNUM];
      95    args->user_entry = auxv_values[AT_ENTRY];
      96  }
      97  
      98  ElfW(Addr)
      99  _dl_sysdep_start (void **start_argptr,
     100  		  void (*dl_main) (const ElfW(Phdr) *phdr, ElfW(Word) phnum,
     101  				   ElfW(Addr) *user_entry, ElfW(auxv_t) *auxv))
     102  {
     103    __libc_stack_end = DL_STACK_END (start_argptr);
     104  
     105    struct dl_main_arguments dl_main_args;
     106    _dl_sysdep_parse_arguments (start_argptr, &dl_main_args);
     107  
     108    dl_hwcap_check ();
     109  
     110    __tunables_init (_environ);
     111  
     112    /* Initialize DSO sorting algorithm after tunables.  */
     113    _dl_sort_maps_init ();
     114  
     115    __brk (0);			/* Initialize the break.  */
     116  
     117  #ifdef DL_PLATFORM_INIT
     118    DL_PLATFORM_INIT;
     119  #endif
     120  
     121    /* Determine the length of the platform name.  */
     122    if (GLRO(dl_platform) != NULL)
     123      GLRO(dl_platformlen) = strlen (GLRO(dl_platform));
     124  
     125    if (__sbrk (0) == _end)
     126      /* The dynamic linker was run as a program, and so the initial break
     127         starts just after our bss, at &_end.  The malloc in dl-minimal.c
     128         will consume the rest of this page, so tell the kernel to move the
     129         break up that far.  When the user program examines its break, it
     130         will see this new value and not clobber our data.  */
     131      __sbrk (GLRO(dl_pagesize)
     132  	    - (((uintptr_t) _end) & (GLRO(dl_pagesize) - 1)));
     133  
     134    /* If this is a SUID program we make sure that FDs 0, 1, and 2 are
     135       allocated.  If necessary we are doing it ourself.  If it is not
     136       possible we stop the program.  */
     137    if (__builtin_expect (__libc_enable_secure, 0))
     138      __libc_check_standard_fds ();
     139  
     140    (*dl_main) (dl_main_args.phdr, dl_main_args.phnum,
     141                &dl_main_args.user_entry, GLRO(dl_auxv));
     142    return dl_main_args.user_entry;
     143  }
     144  
     145  void
     146  _dl_sysdep_start_cleanup (void)
     147  {
     148  }
     149  
     150  void
     151  _dl_show_auxv (void)
     152  {
     153    char buf[64];
     154    ElfW(auxv_t) *av;
     155  
     156    /* Terminate string.  */
     157    buf[63] = '\0';
     158  
     159    /* The following code assumes that the AT_* values are encoded
     160       starting from 0 with AT_NULL, 1 for AT_IGNORE, and all other values
     161       close by (otherwise the array will be too large).  In case we have
     162       to support a platform where these requirements are not fulfilled
     163       some alternative implementation has to be used.  */
     164    for (av = GLRO(dl_auxv); av->a_type != AT_NULL; ++av)
     165      {
     166        static const struct
     167        {
     168  	const char label[22];
     169  	enum { unknown = 0, dec, hex, str, ignore } form : 8;
     170        } auxvars[] =
     171  	{
     172  	  [AT_EXECFD - 2] =		{ "EXECFD:            ", dec },
     173  	  [AT_EXECFN - 2] =		{ "EXECFN:            ", str },
     174  	  [AT_PHDR - 2] =		{ "PHDR:              0x", hex },
     175  	  [AT_PHENT - 2] =		{ "PHENT:             ", dec },
     176  	  [AT_PHNUM - 2] =		{ "PHNUM:             ", dec },
     177  	  [AT_PAGESZ - 2] =		{ "PAGESZ:            ", dec },
     178  	  [AT_BASE - 2] =		{ "BASE:              0x", hex },
     179  	  [AT_FLAGS - 2] =		{ "FLAGS:             0x", hex },
     180  	  [AT_ENTRY - 2] =		{ "ENTRY:             0x", hex },
     181  	  [AT_NOTELF - 2] =		{ "NOTELF:            ", hex },
     182  	  [AT_UID - 2] =		{ "UID:               ", dec },
     183  	  [AT_EUID - 2] =		{ "EUID:              ", dec },
     184  	  [AT_GID - 2] =		{ "GID:               ", dec },
     185  	  [AT_EGID - 2] =		{ "EGID:              ", dec },
     186  	  [AT_PLATFORM - 2] =		{ "PLATFORM:          ", str },
     187  	  [AT_HWCAP - 2] =		{ "HWCAP:             ", hex },
     188  	  [AT_CLKTCK - 2] =		{ "CLKTCK:            ", dec },
     189  	  [AT_FPUCW - 2] =		{ "FPUCW:             ", hex },
     190  	  [AT_DCACHEBSIZE - 2] =	{ "DCACHEBSIZE:       0x", hex },
     191  	  [AT_ICACHEBSIZE - 2] =	{ "ICACHEBSIZE:       0x", hex },
     192  	  [AT_UCACHEBSIZE - 2] =	{ "UCACHEBSIZE:       0x", hex },
     193  	  [AT_IGNOREPPC - 2] =		{ "IGNOREPPC", ignore },
     194  	  [AT_SECURE - 2] =		{ "SECURE:            ", dec },
     195  	  [AT_BASE_PLATFORM - 2] =	{ "BASE_PLATFORM:     ", str },
     196  	  [AT_SYSINFO - 2] =		{ "SYSINFO:           0x", hex },
     197  	  [AT_SYSINFO_EHDR - 2] =	{ "SYSINFO_EHDR:      0x", hex },
     198  	  [AT_RANDOM - 2] =		{ "RANDOM:            0x", hex },
     199  	  [AT_HWCAP2 - 2] =		{ "HWCAP2:            0x", hex },
     200  	  [AT_MINSIGSTKSZ - 2] =	{ "MINSIGSTKSZ:       ", dec },
     201  	  [AT_L1I_CACHESIZE - 2] =	{ "L1I_CACHESIZE:     ", dec },
     202  	  [AT_L1I_CACHEGEOMETRY - 2] =	{ "L1I_CACHEGEOMETRY: 0x", hex },
     203  	  [AT_L1D_CACHESIZE - 2] =	{ "L1D_CACHESIZE:     ", dec },
     204  	  [AT_L1D_CACHEGEOMETRY - 2] =	{ "L1D_CACHEGEOMETRY: 0x", hex },
     205  	  [AT_L2_CACHESIZE - 2] =	{ "L2_CACHESIZE:      ", dec },
     206  	  [AT_L2_CACHEGEOMETRY - 2] =	{ "L2_CACHEGEOMETRY:  0x", hex },
     207  	  [AT_L3_CACHESIZE - 2] =	{ "L3_CACHESIZE:      ", dec },
     208  	  [AT_L3_CACHEGEOMETRY - 2] =	{ "L3_CACHEGEOMETRY:  0x", hex },
     209  	};
     210        unsigned int idx = (unsigned int) (av->a_type - 2);
     211  
     212        if ((unsigned int) av->a_type < 2u
     213  	  || (idx < sizeof (auxvars) / sizeof (auxvars[0])
     214  	      && auxvars[idx].form == ignore))
     215  	continue;
     216  
     217        assert (AT_NULL == 0);
     218        assert (AT_IGNORE == 1);
     219  
     220        /* Some entries are handled in a special way per platform.  */
     221        if (_dl_procinfo (av->a_type, av->a_un.a_val) == 0)
     222  	continue;
     223  
     224        if (idx < sizeof (auxvars) / sizeof (auxvars[0])
     225  	  && auxvars[idx].form != unknown)
     226  	{
     227  	  const char *val = (char *) av->a_un.a_val;
     228  
     229  	  if (__builtin_expect (auxvars[idx].form, dec) == dec)
     230  	    val = _itoa ((unsigned long int) av->a_un.a_val,
     231  			 buf + sizeof buf - 1, 10, 0);
     232  	  else if (__builtin_expect (auxvars[idx].form, hex) == hex)
     233  	    val = _itoa ((unsigned long int) av->a_un.a_val,
     234  			 buf + sizeof buf - 1, 16, 0);
     235  
     236  	  _dl_printf ("AT_%s%s\n", auxvars[idx].label, val);
     237  
     238  	  continue;
     239  	}
     240  
     241        /* Unknown value: print a generic line.  */
     242        char buf2[17];
     243        buf2[sizeof (buf2) - 1] = '\0';
     244        const char *val2 = _itoa ((unsigned long int) av->a_un.a_val,
     245  				buf2 + sizeof buf2 - 1, 16, 0);
     246        const char *val =  _itoa ((unsigned long int) av->a_type,
     247  				buf + sizeof buf - 1, 16, 0);
     248        _dl_printf ("AT_??? (0x%s): 0x%s\n", val, val2);
     249      }
     250  }
     251  
     252  #endif /* SHARED */