Blame elf/dl-support.c

Packit Service 82fcde
/* Support for dynamic linking code in static libc.
Packit Service 82fcde
   Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* This file defines some things that for the dynamic linker are defined in
Packit Service 82fcde
   rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking.  */
Packit Service 82fcde
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <libintl.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <ldsodefs.h>
Packit Service 82fcde
#include <dl-machine.h>
Packit Service 82fcde
#include <libc-lock.h>
Packit Service 82fcde
#include <dl-cache.h>
Packit Service 82fcde
#include <dl-librecon.h>
Packit Service 82fcde
#include <dl-procinfo.h>
Packit Service 82fcde
#include <unsecvars.h>
Packit Service 82fcde
#include <hp-timing.h>
Packit Service 82fcde
#include <stackinfo.h>
Packit Service 82fcde
Packit Service 82fcde
extern char *__progname;
Packit Service 82fcde
char **_dl_argv = &__progname;	/* This is checked for some error messages.  */
Packit Service 82fcde
Packit Service 82fcde
/* Name of the architecture.  */
Packit Service 82fcde
const char *_dl_platform;
Packit Service 82fcde
size_t _dl_platformlen;
Packit Service 82fcde
Packit Service 82fcde
int _dl_debug_mask;
Packit Service 82fcde
int _dl_lazy;
Packit Service 82fcde
ElfW(Addr) _dl_use_load_bias = -2;
Packit Service 82fcde
int _dl_dynamic_weak;
Packit Service 82fcde
Packit Service 82fcde
/* If nonzero print warnings about problematic situations.  */
Packit Service 82fcde
int _dl_verbose;
Packit Service 82fcde
Packit Service 82fcde
/* We never do profiling.  */
Packit Service 82fcde
const char *_dl_profile;
Packit Service 82fcde
const char *_dl_profile_output;
Packit Service 82fcde
Packit Service 82fcde
/* Names of shared object for which the RUNPATHs and RPATHs should be
Packit Service 82fcde
   ignored.  */
Packit Service 82fcde
const char *_dl_inhibit_rpath;
Packit Service 82fcde
Packit Service 82fcde
/* The map for the object we will profile.  */
Packit Service 82fcde
struct link_map *_dl_profile_map;
Packit Service 82fcde
Packit Service 82fcde
/* This is the address of the last stack address ever used.  */
Packit Service 82fcde
void *__libc_stack_end;
Packit Service 82fcde
Packit Service 82fcde
/* Path where the binary is found.  */
Packit Service 82fcde
const char *_dl_origin_path;
Packit Service 82fcde
Packit Service 82fcde
/* Nonzero if runtime lookup should not update the .got/.plt.  */
Packit Service 82fcde
int _dl_bind_not;
Packit Service 82fcde
Packit Service 82fcde
/* A dummy link map for the executable, used by dlopen to access the global
Packit Service 82fcde
   scope.  We don't export any symbols ourselves, so this can be minimal.  */
Packit Service 82fcde
static struct link_map _dl_main_map =
Packit Service 82fcde
  {
Packit Service 82fcde
    .l_name = (char *) "",
Packit Service 82fcde
    .l_real = &_dl_main_map,
Packit Service 82fcde
    .l_ns = LM_ID_BASE,
Packit Service 82fcde
    .l_libname = &(struct libname_list) { .name = "", .dont_free = 1 },
Packit Service 82fcde
    .l_searchlist =
Packit Service 82fcde
      {
Packit Service 82fcde
	.r_list = &(struct link_map *) { &_dl_main_map },
Packit Service 82fcde
	.r_nlist = 1,
Packit Service 82fcde
      },
Packit Service 82fcde
    .l_symbolic_searchlist = { .r_list = &(struct link_map *) { NULL } },
Packit Service 82fcde
    .l_type = lt_executable,
Packit Service 82fcde
    .l_scope_mem = { &_dl_main_map.l_searchlist },
Packit Service 82fcde
    .l_scope_max = (sizeof (_dl_main_map.l_scope_mem)
Packit Service 82fcde
		    / sizeof (_dl_main_map.l_scope_mem[0])),
Packit Service 82fcde
    .l_scope = _dl_main_map.l_scope_mem,
Packit Service 82fcde
    .l_local_scope = { &_dl_main_map.l_searchlist },
Packit Service 82fcde
    .l_used = 1,
Packit Service 82fcde
    .l_tls_offset = NO_TLS_OFFSET,
Packit Service 82fcde
    .l_serial = 1,
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
/* Namespace information.  */
Packit Service 82fcde
struct link_namespaces _dl_ns[DL_NNS] =
Packit Service 82fcde
  {
Packit Service 82fcde
    [LM_ID_BASE] =
Packit Service 82fcde
      {
Packit Service 82fcde
	._ns_loaded = &_dl_main_map,
Packit Service 82fcde
	._ns_nloaded = 1,
Packit Service 82fcde
	._ns_main_searchlist = &_dl_main_map.l_searchlist,
Packit Service 82fcde
      }
Packit Service 82fcde
  };
Packit Service 82fcde
size_t _dl_nns = 1;
Packit Service 82fcde
Packit Service 82fcde
/* Incremented whenever something may have been added to dl_loaded. */
Packit Service 82fcde
unsigned long long _dl_load_adds = 1;
Packit Service 82fcde
Packit Service 82fcde
/* Fake scope of the main application.  */
Packit Service 82fcde
struct r_scope_elem _dl_initial_searchlist =
Packit Service 82fcde
  {
Packit Service 82fcde
    .r_list = &(struct link_map *) { &_dl_main_map },
Packit Service 82fcde
    .r_nlist = 1,
Packit Service 82fcde
  };
Packit Service 82fcde
Packit Service 82fcde
/* Nonzero during startup.  */
Packit Service 82fcde
int _dl_starting_up = 1;
Packit Service 82fcde
Packit Service 82fcde
/* Random data provided by the kernel.  */
Packit Service 82fcde
void *_dl_random;
Packit Service 82fcde
Packit Service 82fcde
/* Get architecture specific initializer.  */
Packit Service 82fcde
#include <dl-procruntime.c>
Packit Service 82fcde
#include <dl-procinfo.c>
Packit Service 82fcde
Packit Service 82fcde
void (*_dl_init_static_tls) (struct link_map *) = &_dl_nothread_init_static_tls;
Packit Service 82fcde
Packit Service 82fcde
size_t _dl_pagesize = EXEC_PAGESIZE;
Packit Service 82fcde
Packit Service 82fcde
int _dl_inhibit_cache;
Packit Service 82fcde
Packit Service 82fcde
unsigned int _dl_osversion;
Packit Service 82fcde
Packit Service 82fcde
/* All known directories in sorted order.  */
Packit Service 82fcde
struct r_search_path_elem *_dl_all_dirs;
Packit Service 82fcde
Packit Service 82fcde
/* All directories after startup.  */
Packit Service 82fcde
struct r_search_path_elem *_dl_init_all_dirs;
Packit Service 82fcde
Packit Service 82fcde
/* The object to be initialized first.  */
Packit Service 82fcde
struct link_map *_dl_initfirst;
Packit Service 82fcde
Packit Service 82fcde
/* Descriptor to write debug messages to.  */
Packit Service 82fcde
int _dl_debug_fd = STDERR_FILENO;
Packit Service 82fcde
Packit Service 82fcde
int _dl_correct_cache_id = _DL_CACHE_DEFAULT_ID;
Packit Service 82fcde
Packit Service 82fcde
ElfW(auxv_t) *_dl_auxv;
Packit Service 82fcde
const ElfW(Phdr) *_dl_phdr;
Packit Service 82fcde
size_t _dl_phnum;
Packit Service 82fcde
uint64_t _dl_hwcap __attribute__ ((nocommon));
Packit Service 82fcde
uint64_t _dl_hwcap2 __attribute__ ((nocommon));
Packit Service 82fcde
Packit Service 82fcde
/* The value of the FPU control word the kernel will preset in hardware.  */
Packit Service 82fcde
fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
Packit Service 82fcde
Packit Service 82fcde
#if !HAVE_TUNABLES
Packit Service 82fcde
/* This is not initialized to HWCAP_IMPORTANT, matching the definition
Packit Service 82fcde
   of _dl_important_hwcaps, below, where no hwcap strings are ever
Packit Service 82fcde
   used.  This mask is still used to mediate the lookups in the cache
Packit Service 82fcde
   file.  Since there is no way to set this nonzero (we don't grok the
Packit Service 82fcde
   LD_HWCAP_MASK environment variable here), there is no real point in
Packit Service 82fcde
   setting _dl_hwcap nonzero below, but we do anyway.  */
Packit Service 82fcde
uint64_t _dl_hwcap_mask __attribute__ ((nocommon));
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
/* Prevailing state of the stack.  Generally this includes PF_X, indicating it's
Packit Service 82fcde
 * executable but this isn't true for all platforms.  */
Packit Service 82fcde
ElfW(Word) _dl_stack_flags = DEFAULT_STACK_PERMS;
Packit Service 82fcde
Packit Service 82fcde
/* If loading a shared object requires that we make the stack executable
Packit Service 82fcde
   when it was not, we do it by calling this function.
Packit Service 82fcde
   It returns an errno code or zero on success.  */
Packit Service 82fcde
int (*_dl_make_stack_executable_hook) (void **) = _dl_make_stack_executable;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Function in libpthread to wait for termination of lookups.  */
Packit Service 82fcde
void (*_dl_wait_lookup_done) (void);
Packit Service 82fcde
Packit Service 82fcde
#if !THREAD_GSCOPE_IN_TCB
Packit Service 82fcde
int _dl_thread_gscope_count;
Packit Service 82fcde
#endif
Packit Service 82fcde
struct dl_scope_free_list *_dl_scope_free_list;
Packit Service 82fcde
Packit Service 82fcde
#ifdef NEED_DL_SYSINFO
Packit Service 82fcde
/* Needed for improved syscall handling on at least x86/Linux.  */
Packit Service 82fcde
uintptr_t _dl_sysinfo = DL_SYSINFO_DEFAULT;
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifdef NEED_DL_SYSINFO_DSO
Packit Service 82fcde
/* Address of the ELF headers in the vsyscall page.  */
Packit Service 82fcde
const ElfW(Ehdr) *_dl_sysinfo_dso;
Packit Service 82fcde
Packit Service 82fcde
struct link_map *_dl_sysinfo_map;
Packit Service 82fcde
Packit Service 82fcde
# include "get-dynamic-info.h"
Packit Service 82fcde
#endif
Packit Service 82fcde
#include "setup-vdso.h"
Packit Service 82fcde
Packit Service 82fcde
/* During the program run we must not modify the global data of
Packit Service 82fcde
   loaded shared object simultanously in two threads.  Therefore we
Packit Service 82fcde
   protect `_dl_open' and `_dl_close' in dl-close.c.
Packit Service 82fcde
Packit Service 82fcde
   This must be a recursive lock since the initializer function of
Packit Service 82fcde
   the loaded object might as well require a call to this function.
Packit Service 82fcde
   At this time it is not anymore a problem to modify the tables.  */
Packit Service 82fcde
__rtld_lock_define_initialized_recursive (, _dl_load_lock)
Packit Service 82fcde
/* This lock is used to keep __dl_iterate_phdr from inspecting the
Packit Service 82fcde
   list of loaded objects while an object is added to or removed from
Packit Service 82fcde
   that list.  */
Packit Service 82fcde
__rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#ifdef HAVE_AUX_VECTOR
Packit Service 82fcde
int _dl_clktck;
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_dl_aux_init (ElfW(auxv_t) *av)
Packit Service 82fcde
{
Packit Service 82fcde
  int seen = 0;
Packit Service 82fcde
  uid_t uid = 0;
Packit Service 82fcde
  gid_t gid = 0;
Packit Service 82fcde
Packit Service 82fcde
  _dl_auxv = av;
Packit Service 82fcde
  for (; av->a_type != AT_NULL; ++av)
Packit Service 82fcde
    switch (av->a_type)
Packit Service 82fcde
      {
Packit Service 82fcde
      case AT_PAGESZ:
Packit Service 82fcde
	if (av->a_un.a_val != 0)
Packit Service 82fcde
	  GLRO(dl_pagesize) = av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_CLKTCK:
Packit Service 82fcde
	GLRO(dl_clktck) = av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_PHDR:
Packit Service 82fcde
	GL(dl_phdr) = (const void *) av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_PHNUM:
Packit Service 82fcde
	GL(dl_phnum) = av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_PLATFORM:
Packit Service 82fcde
	GLRO(dl_platform) = (void *) av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_HWCAP:
Packit Service 82fcde
	GLRO(dl_hwcap) = (unsigned long int) av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_HWCAP2:
Packit Service 82fcde
	GLRO(dl_hwcap2) = (unsigned long int) av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_FPUCW:
Packit Service 82fcde
	GLRO(dl_fpu_control) = av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
#ifdef NEED_DL_SYSINFO
Packit Service 82fcde
      case AT_SYSINFO:
Packit Service 82fcde
	GL(dl_sysinfo) = av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
#endif
Packit Service 82fcde
#ifdef NEED_DL_SYSINFO_DSO
Packit Service 82fcde
      case AT_SYSINFO_EHDR:
Packit Service 82fcde
	GL(dl_sysinfo_dso) = (void *) av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
#endif
Packit Service 82fcde
      case AT_UID:
Packit Service 82fcde
	uid ^= av->a_un.a_val;
Packit Service 82fcde
	seen |= 1;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_EUID:
Packit Service 82fcde
	uid ^= av->a_un.a_val;
Packit Service 82fcde
	seen |= 2;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_GID:
Packit Service 82fcde
	gid ^= av->a_un.a_val;
Packit Service 82fcde
	seen |= 4;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_EGID:
Packit Service 82fcde
	gid ^= av->a_un.a_val;
Packit Service 82fcde
	seen |= 8;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_SECURE:
Packit Service 82fcde
	seen = -1;
Packit Service 82fcde
	__libc_enable_secure = av->a_un.a_val;
Packit Service 82fcde
	__libc_enable_secure_decided = 1;
Packit Service 82fcde
	break;
Packit Service 82fcde
      case AT_RANDOM:
Packit Service 82fcde
	_dl_random = (void *) av->a_un.a_val;
Packit Service 82fcde
	break;
Packit Service 82fcde
# ifdef DL_PLATFORM_AUXV
Packit Service 82fcde
      DL_PLATFORM_AUXV
Packit Service 82fcde
# endif
Packit Service 82fcde
      }
Packit Service 82fcde
  if (seen == 0xf)
Packit Service 82fcde
    {
Packit Service 82fcde
      __libc_enable_secure = uid != 0 || gid != 0;
Packit Service 82fcde
      __libc_enable_secure_decided = 1;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
void
Packit Service 82fcde
_dl_non_dynamic_init (void)
Packit Service 82fcde
{
Packit Service 82fcde
  _dl_main_map.l_origin = _dl_get_origin ();
Packit Service 82fcde
  _dl_main_map.l_phdr = GL(dl_phdr);
Packit Service 82fcde
  _dl_main_map.l_phnum = GL(dl_phnum);
Packit Service 82fcde
Packit Service 82fcde
  _dl_verbose = *(getenv ("LD_WARN") ?: "") == '\0' ? 0 : 1;
Packit Service 82fcde
Packit Service 82fcde
  /* Set up the data structures for the system-supplied DSO early,
Packit Service 82fcde
     so they can influence _dl_init_paths.  */
Packit Service 82fcde
  setup_vdso (NULL, NULL);
Packit Service 82fcde
Packit Service 82fcde
  /* Initialize the data structures for the search paths for shared
Packit Service 82fcde
     objects.  */
Packit Service 82fcde
  _dl_init_paths (getenv ("LD_LIBRARY_PATH"));
Packit Service 82fcde
Packit Service 82fcde
  /* Remember the last search directory added at startup.  */
Packit Service 82fcde
  _dl_init_all_dirs = GL(dl_all_dirs);
Packit Service 82fcde
Packit Service 82fcde
  _dl_lazy = *(getenv ("LD_BIND_NOW") ?: "") == '\0';
Packit Service 82fcde
Packit Service 82fcde
  _dl_bind_not = *(getenv ("LD_BIND_NOT") ?: "") != '\0';
Packit Service 82fcde
Packit Service 82fcde
  _dl_dynamic_weak = *(getenv ("LD_DYNAMIC_WEAK") ?: "") == '\0';
Packit Service 82fcde
Packit Service 82fcde
  _dl_profile_output = getenv ("LD_PROFILE_OUTPUT");
Packit Service 82fcde
  if (_dl_profile_output == NULL || _dl_profile_output[0] == '\0')
Packit Service 82fcde
    _dl_profile_output
Packit Service 82fcde
      = &"/var/tmp\0/var/profile"[__libc_enable_secure ? 9 : 0];
Packit Service 82fcde
Packit Service 82fcde
  if (__libc_enable_secure)
Packit Service 82fcde
    {
Packit Service 82fcde
      static const char unsecure_envvars[] =
Packit Service 82fcde
	UNSECURE_ENVVARS
Packit Service 82fcde
#ifdef EXTRA_UNSECURE_ENVVARS
Packit Service 82fcde
	EXTRA_UNSECURE_ENVVARS
Packit Service 82fcde
#endif
Packit Service 82fcde
	;
Packit Service 82fcde
      const char *cp = unsecure_envvars;
Packit Service 82fcde
Packit Service 82fcde
      while (cp < unsecure_envvars + sizeof (unsecure_envvars))
Packit Service 82fcde
	{
Packit Service 82fcde
	  __unsetenv (cp);
Packit Service 82fcde
	  cp = (const char *) __rawmemchr (cp, '\0') + 1;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
#if !HAVE_TUNABLES
Packit Service 82fcde
      if (__access ("/etc/suid-debug", F_OK) != 0)
Packit Service 82fcde
	__unsetenv ("MALLOC_CHECK_");
Packit Service 82fcde
#endif
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
#ifdef DL_PLATFORM_INIT
Packit Service 82fcde
  DL_PLATFORM_INIT;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifdef DL_OSVERSION_INIT
Packit Service 82fcde
  DL_OSVERSION_INIT;
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
  /* Now determine the length of the platform string.  */
Packit Service 82fcde
  if (_dl_platform != NULL)
Packit Service 82fcde
    _dl_platformlen = strlen (_dl_platform);
Packit Service 82fcde
Packit Service 82fcde
  /* Scan for a program header telling us the stack is nonexecutable.  */
Packit Service 82fcde
  if (_dl_phdr != NULL)
Packit Service 82fcde
    for (uint_fast16_t i = 0; i < _dl_phnum; ++i)
Packit Service 82fcde
      if (_dl_phdr[i].p_type == PT_GNU_STACK)
Packit Service 82fcde
	{
Packit Service 82fcde
	  _dl_stack_flags = _dl_phdr[i].p_flags;
Packit Service 82fcde
	  break;
Packit Service 82fcde
	}
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
#ifdef DL_SYSINFO_IMPLEMENTATION
Packit Service 82fcde
DL_SYSINFO_IMPLEMENTATION
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#if ENABLE_STATIC_PIE
Packit Service 82fcde
/* Since relocation to hidden _dl_main_map causes relocation overflow on
Packit Service 82fcde
   aarch64, a function is used to get the address of _dl_main_map.  */
Packit Service 82fcde
Packit Service 82fcde
struct link_map *
Packit Service 82fcde
_dl_get_dl_main_map (void)
Packit Service 82fcde
{
Packit Service 82fcde
  return &_dl_main_map;
Packit Service 82fcde
}
Packit Service 82fcde
#endif