1 /* Dynamic linker system dependencies for Linux.
2    Copyright (C) 1995-2022 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
_dl_sysdep_parse_arguments(void ** start_argptr,struct dl_main_arguments * args)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)
_dl_sysdep_start(void ** start_argptr,void (* dl_main)(const ElfW (Phdr)* phdr,ElfW (Word)phnum,ElfW (Addr)* user_entry,ElfW (auxv_t)* auxv))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 	    - ((_end - (char *) 0) & (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
_dl_sysdep_start_cleanup(void)146 _dl_sysdep_start_cleanup (void)
147 {
148 }
149 
150 void
_dl_show_auxv(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 */
253