1 /* Miscellaneous support functions for dynamic linker
2    Copyright (C) 1997-2021 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 <assert.h>
20 #include <fcntl.h>
21 #include <ldsodefs.h>
22 #include <limits.h>
23 #include <link.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <stdint.h>
29 #include <sys/mman.h>
30 #include <sys/param.h>
31 #include <sys/stat.h>
32 #include <sys/uio.h>
33 #include <sysdep.h>
34 #include <_itoa.h>
35 #include <dl-writev.h>
36 #include <not-cancel.h>
37 
38 /* Read the whole contents of FILE into new mmap'd space with given
39    protections.  *SIZEP gets the size of the file.  On error MAP_FAILED
40    is returned.  */
41 
42 void *
_dl_sysdep_read_whole_file(const char * file,size_t * sizep,int prot)43 _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
44 {
45   void *result = MAP_FAILED;
46   struct __stat64_t64 st;
47   int fd = __open64_nocancel (file, O_RDONLY | O_CLOEXEC);
48   if (fd >= 0)
49     {
50       if (__fstat64_time64 (fd, &st) >= 0)
51 	{
52 	  *sizep = st.st_size;
53 
54 	  /* No need to map the file if it is empty.  */
55 	  if (*sizep != 0)
56 	    /* Map a copy of the file contents.  */
57 	    result = __mmap (NULL, *sizep, prot,
58 #ifdef MAP_COPY
59 			     MAP_COPY
60 #else
61 			     MAP_PRIVATE
62 #endif
63 #ifdef MAP_FILE
64 			     | MAP_FILE
65 #endif
66 			     , fd, 0);
67 	}
68       __close_nocancel (fd);
69     }
70   return result;
71 }
72 
73 
74 /* Bare-bones printf implementation.  This function only knows about
75    the formats and flags needed and can handle only up to 64 stripes in
76    the output.  */
77 static void
_dl_debug_vdprintf(int fd,int tag_p,const char * fmt,va_list arg)78 _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
79 {
80 # define NIOVMAX 64
81   struct iovec iov[NIOVMAX];
82   int niov = 0;
83   pid_t pid = 0;
84   char pidbuf[12];
85 
86   while (*fmt != '\0')
87     {
88       const char *startp = fmt;
89 
90       if (tag_p > 0)
91 	{
92 	  /* Generate the tag line once.  It consists of the PID and a
93 	     colon followed by a tab.  */
94 	  if (pid == 0)
95 	    {
96 	      char *p;
97 	      pid = __getpid ();
98 	      assert (pid >= 0 && sizeof (pid_t) <= 4);
99 	      p = _itoa (pid, &pidbuf[10], 10, 0);
100 	      while (p > pidbuf)
101 		*--p = ' ';
102 	      pidbuf[10] = ':';
103 	      pidbuf[11] = '\t';
104 	    }
105 
106 	  /* Append to the output.  */
107 	  assert (niov < NIOVMAX);
108 	  iov[niov].iov_len = 12;
109 	  iov[niov++].iov_base = pidbuf;
110 
111 	  /* No more tags until we see the next newline.  */
112 	  tag_p = -1;
113 	}
114 
115       /* Skip everything except % and \n (if tags are needed).  */
116       while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n'))
117 	++fmt;
118 
119       /* Append constant string.  */
120       assert (niov < NIOVMAX);
121       if ((iov[niov].iov_len = fmt - startp) != 0)
122 	iov[niov++].iov_base = (char *) startp;
123 
124       if (*fmt == '%')
125 	{
126 	  /* It is a format specifier.  */
127 	  char fill = ' ';
128 	  int width = -1;
129 	  int prec = -1;
130 #if LONG_MAX != INT_MAX
131 	  int long_mod = 0;
132 #endif
133 
134 	  /* Recognize zero-digit fill flag.  */
135 	  if (*++fmt == '0')
136 	    {
137 	      fill = '0';
138 	      ++fmt;
139 	    }
140 
141 	  /* See whether with comes from a parameter.  Note that no other
142 	     way to specify the width is implemented.  */
143 	  if (*fmt == '*')
144 	    {
145 	      width = va_arg (arg, int);
146 	      ++fmt;
147 	    }
148 
149 	  /* Handle precision.  */
150 	  if (*fmt == '.' && fmt[1] == '*')
151 	    {
152 	      prec = va_arg (arg, int);
153 	      fmt += 2;
154 	    }
155 
156 	  /* Recognize the l modifier.  It is only important on some
157 	     platforms where long and int have a different size.  We
158 	     can use the same code for size_t.  */
159 	  if (*fmt == 'l' || *fmt == 'Z')
160 	    {
161 #if LONG_MAX != INT_MAX
162 	      long_mod = 1;
163 #endif
164 	      ++fmt;
165 	    }
166 
167 	  switch (*fmt)
168 	    {
169 	      /* Integer formatting.  */
170 	    case 'd':
171 	    case 'u':
172 	    case 'x':
173 	      {
174 		/* We have to make a difference if long and int have a
175 		   different size.  */
176 #if LONG_MAX != INT_MAX
177 		unsigned long int num = (long_mod
178 					 ? va_arg (arg, unsigned long int)
179 					 : va_arg (arg, unsigned int));
180 #else
181 		unsigned long int num = va_arg (arg, unsigned int);
182 #endif
183 		bool negative = false;
184 		if (*fmt == 'd')
185 		  {
186 #if LONG_MAX != INT_MAX
187 		    if (long_mod)
188 		      {
189 			if ((long int) num < 0)
190 			  negative = true;
191 		      }
192 		    else
193 		      {
194 			if ((int) num < 0)
195 			  {
196 			    num = (unsigned int) num;
197 			    negative = true;
198 			  }
199 		      }
200 #else
201 		    if ((int) num < 0)
202 		      negative = true;
203 #endif
204 		  }
205 
206 		/* We use alloca() to allocate the buffer with the most
207 		   pessimistic guess for the size.  Using alloca() allows
208 		   having more than one integer formatting in a call.  */
209 		char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int));
210 		char *endp = &buf[1 + 3 * sizeof (unsigned long int)];
211 		char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
212 
213 		/* Pad to the width the user specified.  */
214 		if (width != -1)
215 		  while (endp - cp < width)
216 		    *--cp = fill;
217 
218 		if (negative)
219 		  *--cp = '-';
220 
221 		iov[niov].iov_base = cp;
222 		iov[niov].iov_len = endp - cp;
223 		++niov;
224 	      }
225 	      break;
226 
227 	    case 's':
228 	      /* Get the string argument.  */
229 	      iov[niov].iov_base = va_arg (arg, char *);
230 	      iov[niov].iov_len = strlen (iov[niov].iov_base);
231 	      if (prec != -1)
232 		iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
233 	      ++niov;
234 	      break;
235 
236 	    case '%':
237 	      iov[niov].iov_base = (void *) fmt;
238 	      iov[niov].iov_len = 1;
239 	      ++niov;
240 	      break;
241 
242 	    default:
243 	      assert (! "invalid format specifier");
244 	    }
245 	  ++fmt;
246 	}
247       else if (*fmt == '\n')
248 	{
249 	  /* See whether we have to print a single newline character.  */
250 	  if (fmt == startp)
251 	    {
252 	      iov[niov].iov_base = (char *) startp;
253 	      iov[niov++].iov_len = 1;
254 	    }
255 	  else
256 	    /* No, just add it to the rest of the string.  */
257 	    ++iov[niov - 1].iov_len;
258 
259 	  /* Next line, print a tag again.  */
260 	  tag_p = 1;
261 	  ++fmt;
262 	}
263     }
264 
265   /* Finally write the result.  */
266   _dl_writev (fd, iov, niov);
267 }
268 
269 
270 /* Write to debug file.  */
271 void
_dl_debug_printf(const char * fmt,...)272 _dl_debug_printf (const char *fmt, ...)
273 {
274   va_list arg;
275 
276   va_start (arg, fmt);
277   _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg);
278   va_end (arg);
279 }
280 
281 
282 /* Write to debug file but don't start with a tag.  */
283 void
_dl_debug_printf_c(const char * fmt,...)284 _dl_debug_printf_c (const char *fmt, ...)
285 {
286   va_list arg;
287 
288   va_start (arg, fmt);
289   _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg);
290   va_end (arg);
291 }
292 
293 
294 /* Write the given file descriptor.  */
295 void
_dl_dprintf(int fd,const char * fmt,...)296 _dl_dprintf (int fd, const char *fmt, ...)
297 {
298   va_list arg;
299 
300   va_start (arg, fmt);
301   _dl_debug_vdprintf (fd, 0, fmt, arg);
302   va_end (arg);
303 }
304 
305 void
_dl_printf(const char * fmt,...)306 _dl_printf (const char *fmt, ...)
307 {
308   va_list arg;
309 
310   va_start (arg, fmt);
311   _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg);
312   va_end (arg);
313 }
314 
315 void
_dl_error_printf(const char * fmt,...)316 _dl_error_printf (const char *fmt, ...)
317 {
318   va_list arg;
319 
320   va_start (arg, fmt);
321   _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
322   va_end (arg);
323 }
324 
325 void
_dl_fatal_printf(const char * fmt,...)326 _dl_fatal_printf (const char *fmt, ...)
327 {
328   va_list arg;
329 
330   va_start (arg, fmt);
331   _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg);
332   va_end (arg);
333   _exit (127);
334 }
rtld_hidden_def(_dl_fatal_printf)335 rtld_hidden_def (_dl_fatal_printf)
336 
337 /* Test whether given NAME matches any of the names of the given object.  */
338 int
339 _dl_name_match_p (const char *name, const struct link_map *map)
340 {
341   if (strcmp (name, map->l_name) == 0)
342     return 1;
343 
344   struct libname_list *runp = map->l_libname;
345 
346   while (runp != NULL)
347     if (strcmp (name, runp->name) == 0)
348       return 1;
349     else
350       /* Synchronize with the release MO store in add_name_to_object.
351 	 See CONCURRENCY NOTES in add_name_to_object in dl-load.c.  */
352       runp = atomic_load_acquire (&runp->next);
353 
354   return 0;
355 }
356 
357 
358 unsigned long int
_dl_higher_prime_number(unsigned long int n)359 _dl_higher_prime_number (unsigned long int n)
360 {
361   /* These are primes that are near, but slightly smaller than, a
362      power of two.  */
363   static const uint32_t primes[] = {
364     UINT32_C (7),
365     UINT32_C (13),
366     UINT32_C (31),
367     UINT32_C (61),
368     UINT32_C (127),
369     UINT32_C (251),
370     UINT32_C (509),
371     UINT32_C (1021),
372     UINT32_C (2039),
373     UINT32_C (4093),
374     UINT32_C (8191),
375     UINT32_C (16381),
376     UINT32_C (32749),
377     UINT32_C (65521),
378     UINT32_C (131071),
379     UINT32_C (262139),
380     UINT32_C (524287),
381     UINT32_C (1048573),
382     UINT32_C (2097143),
383     UINT32_C (4194301),
384     UINT32_C (8388593),
385     UINT32_C (16777213),
386     UINT32_C (33554393),
387     UINT32_C (67108859),
388     UINT32_C (134217689),
389     UINT32_C (268435399),
390     UINT32_C (536870909),
391     UINT32_C (1073741789),
392     UINT32_C (2147483647),
393 				       /* 4294967291L */
394     UINT32_C (2147483647) + UINT32_C (2147483644)
395   };
396 
397   const uint32_t *low = &primes[0];
398   const uint32_t *high = &primes[sizeof (primes) / sizeof (primes[0])];
399 
400   while (low != high)
401     {
402       const uint32_t *mid = low + (high - low) / 2;
403       if (n > *mid)
404        low = mid + 1;
405       else
406        high = mid;
407     }
408 
409 #if 0
410   /* If we've run out of primes, abort.  */
411   if (n > *low)
412     {
413       fprintf (stderr, "Cannot find prime bigger than %lu\n", n);
414       abort ();
415     }
416 #endif
417 
418   return *low;
419 }
420 
421 /* A stripped down strtoul-like implementation for very early use.  It
422    does not set errno if the result is outside bounds because it may get
423    called before errno may have been set up.  */
424 
425 uint64_t
_dl_strtoul(const char * nptr,char ** endptr)426 _dl_strtoul (const char *nptr, char **endptr)
427 {
428   uint64_t result = 0;
429   bool positive = true;
430   unsigned max_digit;
431 
432   while (*nptr == ' ' || *nptr == '\t')
433     ++nptr;
434 
435   if (*nptr == '-')
436     {
437       positive = false;
438       ++nptr;
439     }
440   else if (*nptr == '+')
441     ++nptr;
442 
443   if (*nptr < '0' || *nptr > '9')
444     {
445       if (endptr != NULL)
446 	*endptr = (char *) nptr;
447       return 0UL;
448     }
449 
450   int base = 10;
451   max_digit = 9;
452   if (*nptr == '0')
453     {
454       if (nptr[1] == 'x' || nptr[1] == 'X')
455 	{
456 	  base = 16;
457 	  nptr += 2;
458 	}
459       else
460 	{
461 	  base = 8;
462 	  max_digit = 7;
463 	}
464     }
465 
466   while (1)
467     {
468       int digval;
469       if (*nptr >= '0' && *nptr <= '0' + max_digit)
470         digval = *nptr - '0';
471       else if (base == 16)
472         {
473 	  if (*nptr >= 'a' && *nptr <= 'f')
474 	    digval = *nptr - 'a' + 10;
475 	  else if (*nptr >= 'A' && *nptr <= 'F')
476 	    digval = *nptr - 'A' + 10;
477 	  else
478 	    break;
479 	}
480       else
481         break;
482 
483       if (result >= (UINT64_MAX - digval) / base)
484 	{
485 	  if (endptr != NULL)
486 	    *endptr = (char *) nptr;
487 	  return UINT64_MAX;
488 	}
489       result *= base;
490       result += digval;
491       ++nptr;
492     }
493 
494   if (endptr != NULL)
495     *endptr = (char *) nptr;
496 
497   /* Avoid 64-bit multiplication.  */
498   if (!positive)
499     result = -result;
500 
501   return result;
502 }
503