| 1 | /* Minimal replacements for basic facilities used in the dynamic linker. | 
|---|
| 2 | Copyright (C) 1995-2020 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 <errno.h> | 
|---|
| 20 | #include <limits.h> | 
|---|
| 21 | #include <stdio.h> | 
|---|
| 22 | #include <string.h> | 
|---|
| 23 | #include <tls.h> | 
|---|
| 24 | #include <unistd.h> | 
|---|
| 25 | #include <sys/mman.h> | 
|---|
| 26 | #include <sys/param.h> | 
|---|
| 27 | #include <sys/types.h> | 
|---|
| 28 | #include <ldsodefs.h> | 
|---|
| 29 | #include <dl-irel.h> | 
|---|
| 30 | #include <dl-hash.h> | 
|---|
| 31 | #include <dl-sym-post.h> | 
|---|
| 32 | #include <_itoa.h> | 
|---|
| 33 | #include <malloc/malloc-internal.h> | 
|---|
| 34 |  | 
|---|
| 35 | #include <assert.h> | 
|---|
| 36 |  | 
|---|
| 37 | /* The rtld startup code calls __rtld_malloc_init_stubs after the | 
|---|
| 38 | first self-relocation to adjust the pointers to the minimal | 
|---|
| 39 | implementation below.  Before the final relocation, | 
|---|
| 40 | __rtld_malloc_init_real is called to replace the pointers with the | 
|---|
| 41 | real implementation.  */ | 
|---|
| 42 | __typeof (calloc) *__rtld_calloc attribute_relro; | 
|---|
| 43 | __typeof (free) *__rtld_free attribute_relro; | 
|---|
| 44 | __typeof (malloc) *__rtld_malloc attribute_relro; | 
|---|
| 45 | __typeof (realloc) *__rtld_realloc attribute_relro; | 
|---|
| 46 |  | 
|---|
| 47 | /* Defined below.  */ | 
|---|
| 48 | static __typeof (calloc) rtld_calloc; | 
|---|
| 49 | static __typeof (free) rtld_free; | 
|---|
| 50 | static __typeof (malloc) rtld_malloc; | 
|---|
| 51 | static __typeof (realloc) rtld_realloc; | 
|---|
| 52 |  | 
|---|
| 53 | void | 
|---|
| 54 | __rtld_malloc_init_stubs (void) | 
|---|
| 55 | { | 
|---|
| 56 | __rtld_calloc = &rtld_calloc; | 
|---|
| 57 | __rtld_free = &rtld_free; | 
|---|
| 58 | __rtld_malloc = &rtld_malloc; | 
|---|
| 59 | __rtld_realloc = &rtld_realloc; | 
|---|
| 60 | } | 
|---|
| 61 |  | 
|---|
| 62 | /* Lookup NAME at VERSION in the scope of MATCH.  */ | 
|---|
| 63 | static void * | 
|---|
| 64 | lookup_malloc_symbol (struct link_map *main_map, const char *name, | 
|---|
| 65 | struct r_found_version *version) | 
|---|
| 66 | { | 
|---|
| 67 |  | 
|---|
| 68 | const ElfW(Sym) *ref = NULL; | 
|---|
| 69 | lookup_t result = _dl_lookup_symbol_x (name, main_map, &ref, | 
|---|
| 70 | main_map->l_scope, | 
|---|
| 71 | version, 0, 0, NULL); | 
|---|
| 72 |  | 
|---|
| 73 | assert (ELFW(ST_TYPE) (ref->st_info) != STT_TLS); | 
|---|
| 74 | void *value = DL_SYMBOL_ADDRESS (result, ref); | 
|---|
| 75 |  | 
|---|
| 76 | return _dl_sym_post (result, ref, value, 0, main_map); | 
|---|
| 77 | } | 
|---|
| 78 |  | 
|---|
| 79 | void | 
|---|
| 80 | __rtld_malloc_init_real (struct link_map *main_map) | 
|---|
| 81 | { | 
|---|
| 82 | /* We cannot use relocations and initializers for this because the | 
|---|
| 83 | changes made by __rtld_malloc_init_stubs break REL-style | 
|---|
| 84 | (non-RELA) relocations that depend on the previous pointer | 
|---|
| 85 | contents.  Also avoid direct relocation depedencies for the | 
|---|
| 86 | malloc symbols so this function can be called before the final | 
|---|
| 87 | rtld relocation (which enables RELRO, after which the pointer | 
|---|
| 88 | variables cannot be written to).  */ | 
|---|
| 89 |  | 
|---|
| 90 | struct r_found_version version; | 
|---|
| 91 | version.name = symbol_version_string (libc, GLIBC_2_0); | 
|---|
| 92 | version.hidden = 0; | 
|---|
| 93 | version.hash = _dl_elf_hash (version.name); | 
|---|
| 94 | version.filename = NULL; | 
|---|
| 95 |  | 
|---|
| 96 | void *new_calloc = lookup_malloc_symbol (main_map, "calloc", &version); | 
|---|
| 97 | void *new_free = lookup_malloc_symbol (main_map, "free", &version); | 
|---|
| 98 | void *new_malloc = lookup_malloc_symbol (main_map, "malloc", &version); | 
|---|
| 99 | void *new_realloc = lookup_malloc_symbol (main_map, "realloc", &version); | 
|---|
| 100 |  | 
|---|
| 101 | /* Update the pointers in one go, so that any internal allocations | 
|---|
| 102 | performed by lookup_malloc_symbol see a consistent | 
|---|
| 103 | implementation.  */ | 
|---|
| 104 | __rtld_calloc = new_calloc; | 
|---|
| 105 | __rtld_free = new_free; | 
|---|
| 106 | __rtld_malloc = new_malloc; | 
|---|
| 107 | __rtld_realloc = new_realloc; | 
|---|
| 108 | } | 
|---|
| 109 |  | 
|---|
| 110 | /* Minimal malloc allocator for used during initial link.  After the | 
|---|
| 111 | initial link, a full malloc implementation is interposed, either | 
|---|
| 112 | the one in libc, or a different one supplied by the user through | 
|---|
| 113 | interposition.  */ | 
|---|
| 114 |  | 
|---|
| 115 | static void *alloc_ptr, *alloc_end, *alloc_last_block; | 
|---|
| 116 |  | 
|---|
| 117 | /* Allocate an aligned memory block.  */ | 
|---|
| 118 | static void * | 
|---|
| 119 | rtld_malloc (size_t n) | 
|---|
| 120 | { | 
|---|
| 121 | if (alloc_end == 0) | 
|---|
| 122 | { | 
|---|
| 123 | /* Consume any unused space in the last page of our data segment.  */ | 
|---|
| 124 | extern int _end attribute_hidden; | 
|---|
| 125 | alloc_ptr = &_end; | 
|---|
| 126 | alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) | 
|---|
| 127 | + GLRO(dl_pagesize) - 1) | 
|---|
| 128 | & ~(GLRO(dl_pagesize) - 1)); | 
|---|
| 129 | } | 
|---|
| 130 |  | 
|---|
| 131 | /* Make sure the allocation pointer is ideally aligned.  */ | 
|---|
| 132 | alloc_ptr = (void *) 0 + (((alloc_ptr - (void *) 0) + MALLOC_ALIGNMENT - 1) | 
|---|
| 133 | & ~(MALLOC_ALIGNMENT - 1)); | 
|---|
| 134 |  | 
|---|
| 135 | if (alloc_ptr + n >= alloc_end || n >= -(uintptr_t) alloc_ptr) | 
|---|
| 136 | { | 
|---|
| 137 | /* Insufficient space left; allocate another page plus one extra | 
|---|
| 138 | page to reduce number of mmap calls.  */ | 
|---|
| 139 | caddr_t page; | 
|---|
| 140 | size_t nup = (n + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1); | 
|---|
| 141 | if (__glibc_unlikely (nup == 0 && n != 0)) | 
|---|
| 142 | return NULL; | 
|---|
| 143 | nup += GLRO(dl_pagesize); | 
|---|
| 144 | page = __mmap (0, nup, PROT_READ|PROT_WRITE, | 
|---|
| 145 | MAP_ANON|MAP_PRIVATE, -1, 0); | 
|---|
| 146 | if (page == MAP_FAILED) | 
|---|
| 147 | return NULL; | 
|---|
| 148 | if (page != alloc_end) | 
|---|
| 149 | alloc_ptr = page; | 
|---|
| 150 | alloc_end = page + nup; | 
|---|
| 151 | } | 
|---|
| 152 |  | 
|---|
| 153 | alloc_last_block = (void *) alloc_ptr; | 
|---|
| 154 | alloc_ptr += n; | 
|---|
| 155 | return alloc_last_block; | 
|---|
| 156 | } | 
|---|
| 157 |  | 
|---|
| 158 | /* We use this function occasionally since the real implementation may | 
|---|
| 159 | be optimized when it can assume the memory it returns already is | 
|---|
| 160 | set to NUL.  */ | 
|---|
| 161 | static void * | 
|---|
| 162 | rtld_calloc (size_t nmemb, size_t size) | 
|---|
| 163 | { | 
|---|
| 164 | /* New memory from the trivial malloc above is always already cleared. | 
|---|
| 165 | (We make sure that's true in the rare occasion it might not be, | 
|---|
| 166 | by clearing memory in free, below.)  */ | 
|---|
| 167 | size_t bytes = nmemb * size; | 
|---|
| 168 |  | 
|---|
| 169 | #define HALF_SIZE_T (((size_t) 1) << (8 * sizeof (size_t) / 2)) | 
|---|
| 170 | if (__builtin_expect ((nmemb | size) >= HALF_SIZE_T, 0) | 
|---|
| 171 | && size != 0 && bytes / size != nmemb) | 
|---|
| 172 | return NULL; | 
|---|
| 173 |  | 
|---|
| 174 | return malloc (bytes); | 
|---|
| 175 | } | 
|---|
| 176 |  | 
|---|
| 177 | /* This will rarely be called.  */ | 
|---|
| 178 | void | 
|---|
| 179 | rtld_free (void *ptr) | 
|---|
| 180 | { | 
|---|
| 181 | /* We can free only the last block allocated.  */ | 
|---|
| 182 | if (ptr == alloc_last_block) | 
|---|
| 183 | { | 
|---|
| 184 | /* Since this is rare, we clear the freed block here | 
|---|
| 185 | so that calloc can presume malloc returns cleared memory.  */ | 
|---|
| 186 | memset (alloc_last_block, '\0', alloc_ptr - alloc_last_block); | 
|---|
| 187 | alloc_ptr = alloc_last_block; | 
|---|
| 188 | } | 
|---|
| 189 | } | 
|---|
| 190 |  | 
|---|
| 191 | /* This is only called with the most recent block returned by malloc.  */ | 
|---|
| 192 | void * | 
|---|
| 193 | rtld_realloc (void *ptr, size_t n) | 
|---|
| 194 | { | 
|---|
| 195 | if (ptr == NULL) | 
|---|
| 196 | return malloc (n); | 
|---|
| 197 | assert (ptr == alloc_last_block); | 
|---|
| 198 | size_t old_size = alloc_ptr - alloc_last_block; | 
|---|
| 199 | alloc_ptr = alloc_last_block; | 
|---|
| 200 | void *new = malloc (n); | 
|---|
| 201 | return new != ptr ? memcpy (new, ptr, old_size) : new; | 
|---|
| 202 | } | 
|---|
| 203 |  | 
|---|
| 204 | /* Avoid signal frobnication in setjmp/longjmp.  Keeps things smaller.  */ | 
|---|
| 205 |  | 
|---|
| 206 | #include <setjmp.h> | 
|---|
| 207 |  | 
|---|
| 208 | int weak_function | 
|---|
| 209 | __sigjmp_save (sigjmp_buf env, int savemask __attribute__ ((unused))) | 
|---|
| 210 | { | 
|---|
| 211 | env[0].__mask_was_saved = 0; | 
|---|
| 212 | return 0; | 
|---|
| 213 | } | 
|---|
| 214 |  | 
|---|
| 215 | /* Define our own version of the internal function used by strerror.  We | 
|---|
| 216 | only provide the messages for some common errors.  This avoids pulling | 
|---|
| 217 | in the whole error list.  */ | 
|---|
| 218 |  | 
|---|
| 219 | char * weak_function | 
|---|
| 220 | __strerror_r (int errnum, char *buf, size_t buflen) | 
|---|
| 221 | { | 
|---|
| 222 | char *msg; | 
|---|
| 223 |  | 
|---|
| 224 | switch (errnum) | 
|---|
| 225 | { | 
|---|
| 226 | case ENOMEM: | 
|---|
| 227 | msg = (char *) "Cannot allocate memory"; | 
|---|
| 228 | break; | 
|---|
| 229 | case EINVAL: | 
|---|
| 230 | msg = (char *) "Invalid argument"; | 
|---|
| 231 | break; | 
|---|
| 232 | case ENOENT: | 
|---|
| 233 | msg = (char *) "No such file or directory"; | 
|---|
| 234 | break; | 
|---|
| 235 | case EPERM: | 
|---|
| 236 | msg = (char *) "Operation not permitted"; | 
|---|
| 237 | break; | 
|---|
| 238 | case EIO: | 
|---|
| 239 | msg = (char *) "Input/output error"; | 
|---|
| 240 | break; | 
|---|
| 241 | case EACCES: | 
|---|
| 242 | msg = (char *) "Permission denied"; | 
|---|
| 243 | break; | 
|---|
| 244 | default: | 
|---|
| 245 | /* No need to check buffer size, all calls in the dynamic linker | 
|---|
| 246 | provide enough space.  */ | 
|---|
| 247 | buf[buflen - 1] = '\0'; | 
|---|
| 248 | msg = _itoa (errnum, buf + buflen - 1, 10, 0); | 
|---|
| 249 | msg = memcpy (msg - (sizeof ( "Error ") - 1), "Error ", | 
|---|
| 250 | sizeof ( "Error ") - 1); | 
|---|
| 251 | break; | 
|---|
| 252 | } | 
|---|
| 253 |  | 
|---|
| 254 | return msg; | 
|---|
| 255 | } | 
|---|
| 256 |  | 
|---|
| 257 | void | 
|---|
| 258 | __libc_fatal (const char *message) | 
|---|
| 259 | { | 
|---|
| 260 | _dl_fatal_printf ( "%s", message); | 
|---|
| 261 | } | 
|---|
| 262 | rtld_hidden_def (__libc_fatal) | 
|---|
| 263 |  | 
|---|
| 264 | void | 
|---|
| 265 | __attribute__ ((noreturn)) | 
|---|
| 266 | __chk_fail (void) | 
|---|
| 267 | { | 
|---|
| 268 | _exit (127); | 
|---|
| 269 | } | 
|---|
| 270 | rtld_hidden_def (__chk_fail) | 
|---|
| 271 |  | 
|---|
| 272 | #ifndef NDEBUG | 
|---|
| 273 | /* Define (weakly) our own assert failure function which doesn't use stdio. | 
|---|
| 274 | If we are linked into the user program (-ldl), the normal __assert_fail | 
|---|
| 275 | defn can override this one.  */ | 
|---|
| 276 |  | 
|---|
| 277 | void weak_function | 
|---|
| 278 | __assert_fail (const char *assertion, | 
|---|
| 279 | const char *file, unsigned int line, const char *function) | 
|---|
| 280 | { | 
|---|
| 281 | _dl_fatal_printf ( "\ | 
|---|
| 282 | Inconsistency detected by ld.so: %s: %u: %s%sAssertion `%s' failed!\n", | 
|---|
| 283 | file, line, function ?: "", function ? ": ": "", | 
|---|
| 284 | assertion); | 
|---|
| 285 |  | 
|---|
| 286 | } | 
|---|
| 287 | rtld_hidden_weak (__assert_fail) | 
|---|
| 288 |  | 
|---|
| 289 | void weak_function | 
|---|
| 290 | __assert_perror_fail (int errnum, | 
|---|
| 291 | const char *file, unsigned int line, | 
|---|
| 292 | const char *function) | 
|---|
| 293 | { | 
|---|
| 294 | char errbuf[400]; | 
|---|
| 295 | _dl_fatal_printf ( "\ | 
|---|
| 296 | Inconsistency detected by ld.so: %s: %u: %s%sUnexpected error: %s.\n", | 
|---|
| 297 | file, line, function ?: "", function ? ": ": "", | 
|---|
| 298 | __strerror_r (errnum, errbuf, sizeof errbuf)); | 
|---|
| 299 |  | 
|---|
| 300 | } | 
|---|
| 301 | rtld_hidden_weak (__assert_perror_fail) | 
|---|
| 302 | #endif | 
|---|
| 303 |  | 
|---|
| 304 | #undef _itoa | 
|---|
| 305 | /* We always use _itoa instead of _itoa_word in ld.so since the former | 
|---|
| 306 | also has to be present and it is never about speed when these | 
|---|
| 307 | functions are used.  */ | 
|---|
| 308 | char * | 
|---|
| 309 | _itoa (unsigned long long int value, char *buflim, unsigned int base, | 
|---|
| 310 | int upper_case) | 
|---|
| 311 | { | 
|---|
| 312 | assert (! upper_case); | 
|---|
| 313 |  | 
|---|
| 314 | do | 
|---|
| 315 | *--buflim = _itoa_lower_digits[value % base]; | 
|---|
| 316 | while ((value /= base) != 0); | 
|---|
| 317 |  | 
|---|
| 318 | return buflim; | 
|---|
| 319 | } | 
|---|
| 320 |  | 
|---|
| 321 | /* The '_itoa_lower_digits' variable in libc.so is able to handle bases | 
|---|
| 322 | up to 36.  We don't need this here.  */ | 
|---|
| 323 | const char _itoa_lower_digits[16] = "0123456789abcdef"; | 
|---|
| 324 | rtld_hidden_data_def (_itoa_lower_digits) | 
|---|
| 325 |  | 
|---|
| 326 | /* The following is not a complete strsep implementation.  It cannot | 
|---|
| 327 | handle empty delimiter strings.  But this isn't necessary for the | 
|---|
| 328 | execution of ld.so.  */ | 
|---|
| 329 | #undef strsep | 
|---|
| 330 | #undef __strsep | 
|---|
| 331 | char * | 
|---|
| 332 | __strsep (char **stringp, const char *delim) | 
|---|
| 333 | { | 
|---|
| 334 | char *begin; | 
|---|
| 335 |  | 
|---|
| 336 | assert (delim[0] != '\0'); | 
|---|
| 337 |  | 
|---|
| 338 | begin = *stringp; | 
|---|
| 339 | if (begin != NULL) | 
|---|
| 340 | { | 
|---|
| 341 | char *end = begin; | 
|---|
| 342 |  | 
|---|
| 343 | while (*end != '\0' || (end = NULL)) | 
|---|
| 344 | { | 
|---|
| 345 | const char *dp = delim; | 
|---|
| 346 |  | 
|---|
| 347 | do | 
|---|
| 348 | if (*dp == *end) | 
|---|
| 349 | break; | 
|---|
| 350 | while (*++dp != '\0'); | 
|---|
| 351 |  | 
|---|
| 352 | if (*dp != '\0') | 
|---|
| 353 | { | 
|---|
| 354 | *end++ = '\0'; | 
|---|
| 355 | break; | 
|---|
| 356 | } | 
|---|
| 357 |  | 
|---|
| 358 | ++end; | 
|---|
| 359 | } | 
|---|
| 360 |  | 
|---|
| 361 | *stringp = end; | 
|---|
| 362 | } | 
|---|
| 363 |  | 
|---|
| 364 | return begin; | 
|---|
| 365 | } | 
|---|
| 366 | weak_alias (__strsep, strsep) | 
|---|
| 367 | strong_alias (__strsep, __strsep_g) | 
|---|
| 368 |  | 
|---|