aboutsummaryrefslogtreecommitdiff
path: root/elf/rtld.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
committerJakub Jelinek <jakub@redhat.com>2007-07-12 18:26:36 +0000
commit0ecb606cb6cf65de1d9fc8a919bceb4be476c602 (patch)
tree2ea1f8305970753e4a657acb2ccc15ca3eec8e2c /elf/rtld.c
parent7d58530341304d403a6626d7f7a1913165fe2f32 (diff)
downloadglibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.tar.xz
glibc-0ecb606cb6cf65de1d9fc8a919bceb4be476c602.zip
2.5-18.1
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c1043
1 files changed, 733 insertions, 310 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index cd40f80088..a357a46987 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1,5 +1,5 @@
/* Run time dynamic linker.
- Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1995-2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -34,9 +34,10 @@
#include <hp-timing.h>
#include <bits/libc-lock.h>
#include "dynamic-link.h"
-#include "dl-librecon.h"
+#include <dl-librecon.h>
#include <unsecvars.h>
#include <dl-cache.h>
+#include <dl-osinfo.h>
#include <dl-procinfo.h>
#include <tls.h>
@@ -60,6 +61,9 @@ static void print_missing_version (int errcode, const char *objname,
/* Print the various times we collected. */
static void print_statistics (hp_timing_t *total_timep);
+/* Add audit objects. */
+static void process_dl_audit (char *str);
+
/* This is a list of all the modes the dynamic loader can be in. */
enum mode { normal, list, verify, trace };
@@ -68,16 +72,39 @@ enum mode { normal, list, verify, trace };
all the entries. */
static void process_envvars (enum mode *modep);
-int _dl_argc attribute_relro attribute_hidden;
#ifdef DL_ARGV_NOT_RELRO
+int _dl_argc attribute_hidden;
char **_dl_argv = NULL;
+/* Nonzero if we were run directly. */
+unsigned int _dl_skip_args attribute_hidden;
#else
+int _dl_argc attribute_relro attribute_hidden;
char **_dl_argv attribute_relro = NULL;
+unsigned int _dl_skip_args attribute_relro attribute_hidden;
#endif
INTDEF(_dl_argv)
-/* Nonzero if we were run directly. */
-unsigned int _dl_skip_args attribute_relro attribute_hidden;
+#ifndef THREAD_SET_STACK_GUARD
+/* Only exported for architectures that don't store the stack guard canary
+ in thread local area. */
+uintptr_t __stack_chk_guard attribute_relro;
+#endif
+
+/* Only exported for architectures that don't store the pointer guard
+ value in thread local area. */
+uintptr_t __pointer_chk_guard_local
+ attribute_relro attribute_hidden __attribute__ ((nocommon));
+#ifndef THREAD_SET_POINTER_GUARD
+strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
+#endif
+
+
+/* List of auditing DSOs. */
+static struct audit_list
+{
+ const char *name;
+ struct audit_list *next;
+} *audit_list;
#ifndef HAVE_INLINED_SYSCALLS
/* Set nonzero during loading and initialization of executable and
@@ -124,27 +151,17 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
._dl_hwcap_mask = HWCAP_IMPORTANT,
._dl_lazy = 1,
._dl_fpu_control = _FPU_DEFAULT,
+ ._dl_pointer_guard = 1,
/* Function pointers. */
- ._dl_get_origin = _dl_get_origin,
- ._dl_dst_count = _dl_dst_count,
- ._dl_dst_substitute = _dl_dst_substitute,
- ._dl_map_object = _dl_map_object,
- ._dl_map_object_deps = _dl_map_object_deps,
- ._dl_relocate_object = _dl_relocate_object,
- ._dl_check_map_versions = _dl_check_map_versions,
- ._dl_init = _dl_init,
- ._dl_debug_state = _dl_debug_state,
-#ifndef MAP_COPY
- ._dl_unload_cache = _dl_unload_cache,
-#endif
._dl_debug_printf = _dl_debug_printf,
._dl_catch_error = _dl_catch_error,
._dl_signal_error = _dl_signal_error,
- ._dl_start_profile = _dl_start_profile,
._dl_mcount = _dl_mcount_internal,
._dl_lookup_symbol_x = _dl_lookup_symbol_x,
- ._dl_check_caller = _dl_check_caller
+ ._dl_check_caller = _dl_check_caller,
+ ._dl_open = _dl_open,
+ ._dl_close = _dl_close
};
/* If we would use strong_alias here the compiler would see a
non-hidden definition. This would undo the effect of the previous
@@ -267,10 +284,10 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
memcpy (GL(dl_rtld_map).l_info, info->l.l_info,
sizeof GL(dl_rtld_map).l_info);
GL(dl_rtld_map).l_mach = info->l.l_mach;
+ GL(dl_rtld_map).l_relocated = 1;
#endif
_dl_setup_hash (&GL(dl_rtld_map));
GL(dl_rtld_map).l_real = &GL(dl_rtld_map);
- GL(dl_rtld_map).l_opencount = 1;
GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin;
GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end;
GL(dl_rtld_map).l_text_end = (ElfW(Addr)) _etext;
@@ -286,7 +303,6 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
GL(dl_rtld_map).l_tls_offset = info->l.l_tls_offset;
GL(dl_rtld_map).l_tls_modid = 1;
# else
- assert (info->l.l_tls_modid == 0);
# if NO_TLS_OFFSET != 0
GL(dl_rtld_map).l_tls_offset = NO_TLS_OFFSET;
# endif
@@ -348,8 +364,6 @@ _dl_start (void *arg)
#define RTLD_BOOTSTRAP
#define RESOLVE_MAP(sym, version, flags) \
((*(sym))->st_shndx == SHN_UNDEF ? 0 : &bootstrap_map)
-#define RESOLVE(sym, version, flags) \
- ((*(sym))->st_shndx == SHN_UNDEF ? 0 : bootstrap_map.l_addr)
#include "dynamic-link.h"
if (HP_TIMING_INLINE && HP_TIMING_AVAIL)
@@ -374,6 +388,9 @@ _dl_start (void *arg)
++cnt)
bootstrap_map.l_info[cnt] = 0;
# endif
+# if USE___THREAD
+ bootstrap_map.l_tls_modid = 0;
+# endif
#endif
/* Figure out the run-time load address of the dynamic linker itself. */
@@ -472,7 +489,7 @@ _dl_start (void *arg)
while (remaining-- > 0)
*p++ = '\0';
}
-#endif
+# endif
/* Install the pointer to the dtv. */
@@ -515,6 +532,7 @@ _dl_start (void *arg)
ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0);
}
+ bootstrap_map.l_relocated = 1;
/* Please note that we don't allow profiling of this object and
therefore need not test whether we have to allocate the array
@@ -566,6 +584,19 @@ struct map_args
struct link_map *map;
};
+struct dlmopen_args
+{
+ const char *fname;
+ struct link_map *map;
+};
+
+struct lookup_args
+{
+ const char *name;
+ struct link_map *map;
+ void *result;
+};
+
/* Arguments to version_check_doit. */
struct version_check_args
{
@@ -591,6 +622,28 @@ map_doit (void *a)
}
static void
+dlmopen_doit (void *a)
+{
+ struct dlmopen_args *args = (struct dlmopen_args *) a;
+ args->map = _dl_open (args->fname, RTLD_LAZY | __RTLD_DLOPEN | __RTLD_AUDIT,
+ dl_main, LM_ID_NEWLM, _dl_argc, INTUSE(_dl_argv),
+ __environ);
+}
+
+static void
+lookup_doit (void *a)
+{
+ struct lookup_args *args = (struct lookup_args *) a;
+ const ElfW(Sym) *ref = NULL;
+ args->result = NULL;
+ lookup_t l = _dl_lookup_symbol_x (args->name, args->map, &ref,
+ args->map->l_local_scope, NULL, 0,
+ DL_LOOKUP_RETURN_NEWEST, NULL);
+ if (ref != NULL)
+ args->result = DL_SYMBOL_ADDRESS (l, ref);
+}
+
+static void
version_check_doit (void *a)
{
struct version_check_args *args = (struct version_check_args *) a;
@@ -648,6 +701,80 @@ match_version (const char *string, struct link_map *map)
return 0;
}
+#ifdef USE_TLS
+static bool tls_init_tp_called;
+
+static void *
+init_tls (void)
+{
+ /* Number of elements in the static TLS block. */
+ GL(dl_tls_static_nelem) = GL(dl_tls_max_dtv_idx);
+
+ /* Do not do this twice. The audit interface might have required
+ the DTV interfaces to be set up early. */
+ if (GL(dl_initial_dtv) != NULL)
+ return NULL;
+
+ /* Allocate the array which contains the information about the
+ dtv slots. We allocate a few entries more than needed to
+ avoid the need for reallocation. */
+ size_t nelem = GL(dl_tls_max_dtv_idx) + 1 + TLS_SLOTINFO_SURPLUS;
+
+ /* Allocate. */
+ GL(dl_tls_dtv_slotinfo_list) = (struct dtv_slotinfo_list *)
+ calloc (sizeof (struct dtv_slotinfo_list)
+ + nelem * sizeof (struct dtv_slotinfo), 1);
+ /* No need to check the return value. If memory allocation failed
+ the program would have been terminated. */
+
+ struct dtv_slotinfo *slotinfo = GL(dl_tls_dtv_slotinfo_list)->slotinfo;
+ GL(dl_tls_dtv_slotinfo_list)->len = nelem;
+ GL(dl_tls_dtv_slotinfo_list)->next = NULL;
+
+ /* Fill in the information from the loaded modules. No namespace
+ but the base one can be filled at this time. */
+ assert (GL(dl_ns)[LM_ID_BASE + 1]._ns_loaded == NULL);
+ int i = 0;
+ for (struct link_map *l = GL(dl_ns)[LM_ID_BASE]._ns_loaded; l != NULL;
+ l = l->l_next)
+ if (l->l_tls_blocksize != 0)
+ {
+ /* This is a module with TLS data. Store the map reference.
+ The generation counter is zero. */
+ slotinfo[i].map = l;
+ /* slotinfo[i].gen = 0; */
+ ++i;
+ }
+ assert (i == GL(dl_tls_max_dtv_idx));
+
+ /* Compute the TLS offsets for the various blocks. */
+ _dl_determine_tlsoffset ();
+
+ /* Construct the static TLS block and the dtv for the initial
+ thread. For some platforms this will include allocating memory
+ for the thread descriptor. The memory for the TLS block will
+ never be freed. It should be allocated accordingly. The dtv
+ array can be changed if dynamic loading requires it. */
+ void *tcbp = _dl_allocate_tls_storage ();
+ if (tcbp == NULL)
+ _dl_fatal_printf ("\
+cannot allocate TLS data structures for initial thread");
+
+ /* Store for detection of the special case by __tls_get_addr
+ so it knows not to pass this dtv to the normal realloc. */
+ GL(dl_initial_dtv) = GET_DTV (tcbp);
+
+ /* And finally install it for the main thread. If ld.so itself uses
+ TLS we know the thread pointer was initialized earlier. */
+ const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
+ if (__builtin_expect (lossage != NULL, 0))
+ _dl_fatal_printf ("cannot set up thread-local storage: %s\n", lossage);
+ tls_init_tp_called = true;
+
+ return tcbp;
+}
+#endif
+
#ifdef _LIBC_REENTRANT
/* _dl_error_catch_tsd points to this for the single-threaded case.
It's reset by the thread library for multithreaded programs. */
@@ -659,14 +786,49 @@ _dl_initial_error_catch_tsd (void)
}
#endif
+
+static unsigned int
+do_preload (char *fname, struct link_map *main_map, const char *where)
+{
+ const char *objname;
+ const char *err_str = NULL;
+ struct map_args args;
+ bool malloced;
+
+ args.str = fname;
+ args.loader = main_map;
+ args.is_preloaded = 1;
+ args.mode = 0;
+
+ unsigned int old_nloaded = GL(dl_ns)[LM_ID_BASE]._ns_nloaded;
+
+ (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit, &args);
+ if (__builtin_expect (err_str != NULL, 0))
+ {
+ _dl_error_printf ("\
+ERROR: ld.so: object '%s' from %s cannot be preloaded: ignored.\n",
+ fname, where);
+ /* No need to call free, this is still before
+ the libc's malloc is used. */
+ }
+ else if (GL(dl_ns)[LM_ID_BASE]._ns_nloaded != old_nloaded)
+ /* It is no duplicate. */
+ return 1;
+
+ /* Nothing loaded. */
+ return 0;
+}
+
#if defined SHARED && defined _LIBC_REENTRANT \
&& defined __rtld_lock_default_lock_recursive
-static void rtld_lock_default_lock_recursive (void *lock)
+static void
+rtld_lock_default_lock_recursive (void *lock)
{
__rtld_lock_default_lock_recursive (lock);
}
-static void rtld_lock_default_unlock_recursive (void *lock)
+static void
+rtld_lock_default_unlock_recursive (void *lock)
{
__rtld_lock_default_unlock_recursive (lock);
}
@@ -687,8 +849,6 @@ dl_main (const ElfW(Phdr) *phdr,
{
const ElfW(Phdr) *ph;
enum mode mode;
- struct link_map **preloads;
- unsigned int npreloads;
struct link_map *main_map;
size_t file_size;
char *file;
@@ -702,7 +862,7 @@ dl_main (const ElfW(Phdr) *phdr,
hp_timing_t diff;
#endif
#ifdef USE_TLS
- void *tcbp;
+ void *tcbp = NULL;
#endif
#ifdef _LIBC_REENTRANT
@@ -790,6 +950,14 @@ dl_main (const ElfW(Phdr) *phdr,
_dl_argc -= 2;
INTUSE(_dl_argv) += 2;
}
+ else if (! strcmp (INTUSE(_dl_argv)[1], "--audit") && _dl_argc > 2)
+ {
+ process_dl_audit (INTUSE(_dl_argv)[2]);
+
+ _dl_skip_args += 2;
+ _dl_argc -= 2;
+ INTUSE(_dl_argv) += 2;
+ }
else
break;
@@ -822,10 +990,6 @@ of this helper program; chances are you did not intend to run this program.\n\
--_dl_argc;
++INTUSE(_dl_argv);
- /* Initialize the data structures for the search paths for shared
- objects. */
- _dl_init_paths (library_path);
-
/* The initialization of _dl_stack_flags done below assumes the
executable's PT_GNU_STACK may have been honored by the kernel, and
so a PT_GNU_STACK with PF_X set means the stack started out with
@@ -850,12 +1014,14 @@ of this helper program; chances are you did not intend to run this program.\n\
const char *objname;
const char *err_str = NULL;
struct map_args args;
+ bool malloced;
args.str = rtld_progname;
args.loader = NULL;
args.is_preloaded = 0;
args.mode = __RTLD_OPENEXEC;
- (void) _dl_catch_error (&objname, &err_str, map_doit, &args);
+ (void) _dl_catch_error (&objname, &err_str, &malloced, map_doit,
+ &args);
if (__builtin_expect (err_str != NULL, 0))
/* We don't free the returned string, the programs stops
anyway. */
@@ -887,10 +1053,10 @@ of this helper program; chances are you did not intend to run this program.\n\
{
/* Create a link_map for the executable itself.
This will be what dlopen on "" returns. */
- _dl_new_object ((char *) "", "", lt_executable, NULL, 0, LM_ID_BASE);
- main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
- if (main_map == NULL)
- _dl_fatal_printf ("cannot allocate memory for link map\n");
+ main_map = _dl_new_object ((char *) "", "", lt_executable, NULL,
+ __RTLD_OPENEXEC, LM_ID_BASE);
+ assert (main_map != NULL);
+ assert (main_map == GL(dl_ns)[LM_ID_BASE]._ns_loaded);
main_map->l_phdr = phdr;
main_map->l_phnum = phnum;
main_map->l_entry = *user_entry;
@@ -918,8 +1084,6 @@ of this helper program; chances are you did not intend to run this program.\n\
main_map->l_text_end = 0;
/* Perhaps the executable has no PT_LOAD header entries at all. */
main_map->l_map_start = ~0;
- /* We opened the file, account for it. */
- ++main_map->l_opencount;
/* And it was opened directly. */
++main_map->l_direct_opencount;
@@ -991,8 +1155,9 @@ of this helper program; chances are you did not intend to run this program.\n\
main_map->l_text_end = allocend;
}
break;
-#ifdef USE_TLS
+
case PT_TLS:
+#ifdef USE_TLS
if (ph->p_memsz > 0)
{
/* Note that in the case the dynamic linker we duplicate work
@@ -1012,8 +1177,12 @@ of this helper program; chances are you did not intend to run this program.\n\
/* This image gets the ID one. */
GL(dl_tls_max_dtv_idx) = main_map->l_tls_modid = 1;
}
- break;
+#else
+ _dl_fatal_printf ("\
+ld.so does not support TLS, but program uses it!\n");
#endif
+ break;
+
case PT_GNU_STACK:
GL(dl_stack_flags) = ph->p_flags;
break;
@@ -1045,6 +1214,26 @@ of this helper program; chances are you did not intend to run this program.\n\
else
assert (GL(dl_rtld_map).l_libname); /* How else did we get here? */
+ /* If the current libname is different from the SONAME, add the
+ latter as well. */
+ if (GL(dl_rtld_map).l_info[DT_SONAME] != NULL
+ && strcmp (GL(dl_rtld_map).l_libname->name,
+ (const char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+ + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_val) != 0)
+ {
+ static struct libname_list newname;
+ newname.name = ((char *) D_PTR (&GL(dl_rtld_map), l_info[DT_STRTAB])
+ + GL(dl_rtld_map).l_info[DT_SONAME]->d_un.d_ptr);
+ newname.next = NULL;
+ newname.dont_free = 1;
+
+ assert (GL(dl_rtld_map).l_libname->next == NULL);
+ GL(dl_rtld_map).l_libname->next = &newname;
+ }
+ /* The ld.so must be relocated since otherwise loading audit modules
+ will fail since they reuse the very same ld.so. */
+ assert (GL(dl_rtld_map).l_relocated);
+
if (! rtld_is_main)
{
/* Extract the contents of the dynamic section for easy access. */
@@ -1069,10 +1258,110 @@ of this helper program; chances are you did not intend to run this program.\n\
_exit (has_interp ? 0 : 2);
}
- if (! rtld_is_main)
- /* Initialize the data structures for the search paths for shared
- objects. */
- _dl_init_paths (library_path);
+ struct link_map **first_preload = &GL(dl_rtld_map).l_next;
+#if defined NEED_DL_SYSINFO || defined NEED_DL_SYSINFO_DSO
+ /* Set up the data structures for the system-supplied DSO early,
+ so they can influence _dl_init_paths. */
+ if (GLRO(dl_sysinfo_dso) != NULL)
+ {
+ /* Do an abridged version of the work _dl_map_object_from_fd would do
+ to map in the object. It's already mapped and prelinked (and
+ better be, since it's read-only and so we couldn't relocate it).
+ We just want our data structures to describe it as if we had just
+ mapped and relocated it normally. */
+ struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
+ 0, LM_ID_BASE);
+ if (__builtin_expect (l != NULL, 1))
+ {
+ static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;
+
+ l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
+ + GLRO(dl_sysinfo_dso)->e_phoff);
+ l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum;
+ for (uint_fast16_t i = 0; i < l->l_phnum; ++i)
+ {
+ const ElfW(Phdr) *const ph = &l->l_phdr[i];
+ if (ph->p_type == PT_DYNAMIC)
+ {
+ l->l_ld = (void *) ph->p_vaddr;
+ l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
+ }
+ else if (ph->p_type == PT_LOAD)
+ {
+ if (! l->l_addr)
+ l->l_addr = ph->p_vaddr;
+ if (ph->p_vaddr + ph->p_memsz >= l->l_map_end)
+ l->l_map_end = ph->p_vaddr + ph->p_memsz;
+ if ((ph->p_flags & PF_X)
+ && ph->p_vaddr + ph->p_memsz >= l->l_text_end)
+ l->l_text_end = ph->p_vaddr + ph->p_memsz;
+ }
+ else
+ /* There must be no TLS segment. */
+ assert (ph->p_type != PT_TLS);
+ }
+ l->l_map_start = (ElfW(Addr)) GLRO(dl_sysinfo_dso);
+ l->l_addr = l->l_map_start - l->l_addr;
+ l->l_map_end += l->l_addr;
+ l->l_text_end += l->l_addr;
+ l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr);
+ elf_get_dynamic_info (l, dyn_temp);
+ _dl_setup_hash (l);
+ l->l_relocated = 1;
+
+ /* Initialize l_local_scope to contain just this map. This allows
+ the use of dl_lookup_symbol_x to resolve symbols within the vdso.
+ So we create a single entry list pointing to l_real as its only
+ element */
+ l->l_local_scope[0]->r_nlist = 1;
+ l->l_local_scope[0]->r_list = &l->l_real;
+
+ /* Now that we have the info handy, use the DSO image's soname
+ so this object can be looked up by name. Note that we do not
+ set l_name here. That field gives the file name of the DSO,
+ and this DSO is not associated with any file. */
+ if (l->l_info[DT_SONAME] != NULL)
+ {
+ /* Work around a kernel problem. The kernel cannot handle
+ addresses in the vsyscall DSO pages in writev() calls. */
+ const char *dsoname = ((char *) D_PTR (l, l_info[DT_STRTAB])
+ + l->l_info[DT_SONAME]->d_un.d_val);
+ size_t len = strlen (dsoname);
+ char *copy = malloc (len);
+ if (copy == NULL)
+ _dl_fatal_printf ("out of memory\n");
+ l->l_libname->name = memcpy (copy, dsoname, len);
+ }
+
+ /* Rearrange the list so this DSO appears after rtld_map. */
+ assert (l->l_next == NULL);
+ assert (l->l_prev == main_map);
+ GL(dl_rtld_map).l_next = l;
+ l->l_prev = &GL(dl_rtld_map);
+ first_preload = &l->l_next;
+
+ /* We have a prelinked DSO preloaded by the system. */
+ GLRO(dl_sysinfo_map) = l;
+# ifdef NEED_DL_SYSINFO
+ if (GLRO(dl_sysinfo) == DL_SYSINFO_DEFAULT)
+ GLRO(dl_sysinfo) = GLRO(dl_sysinfo_dso)->e_entry + l->l_addr;
+# endif
+ }
+ }
+#endif
+
+#ifdef DL_SYSDEP_OSCHECK
+ DL_SYSDEP_OSCHECK (dl_fatal);
+#endif
+
+ /* Initialize the data structures for the search paths for shared
+ objects. */
+ _dl_init_paths (library_path);
+
+ /* Initialize _r_debug. */
+ struct r_debug *r = _dl_debug_initialize (GL(dl_rtld_map).l_addr,
+ LM_ID_BASE);
+ r->r_state = RT_CONSISTENT;
/* Put the link_map for ourselves on the chain so it can be found by
name. Note that at this point the global chain of link maps contains
@@ -1101,6 +1390,7 @@ of this helper program; chances are you did not intend to run this program.\n\
GL(dl_rtld_map).l_phdr = rtld_phdr;
GL(dl_rtld_map).l_phnum = rtld_ehdr->e_phnum;
+
/* PT_GNU_RELRO is usually the last phdr. */
size_t cnt = rtld_ehdr->e_phnum;
while (cnt-- > 0)
@@ -1111,11 +1401,229 @@ of this helper program; chances are you did not intend to run this program.\n\
break;
}
+#ifdef USE_TLS
+ /* Add the dynamic linker to the TLS list if it also uses TLS. */
+ if (GL(dl_rtld_map).l_tls_blocksize != 0)
+ /* Assign a module ID. Do this before loading any audit modules. */
+ GL(dl_rtld_map).l_tls_modid = _dl_next_tls_modid ();
+#endif
+
+ /* If we have auditing DSOs to load, do it now. */
+ if (__builtin_expect (audit_list != NULL, 0))
+ {
+ /* Iterate over all entries in the list. The order is important. */
+ struct audit_ifaces *last_audit = NULL;
+ struct audit_list *al = audit_list->next;
+
+#ifdef USE_TLS
+ /* Since we start using the auditing DSOs right away we need to
+ initialize the data structures now. */
+ tcbp = init_tls ();
+#endif
+ do
+ {
+#ifdef USE_TLS
+ int tls_idx = GL(dl_tls_max_dtv_idx);
+
+ /* Now it is time to determine the layout of the static TLS
+ block and allocate it for the initial thread. Note that we
+ always allocate the static block, we never defer it even if
+ no DF_STATIC_TLS bit is set. The reason is that we know
+ glibc will use the static model. */
+#endif
+ struct dlmopen_args dlmargs;
+ dlmargs.fname = al->name;
+ dlmargs.map = NULL;
+
+ const char *objname;
+ const char *err_str = NULL;
+ bool malloced;
+ (void) _dl_catch_error (&objname, &err_str, &malloced, dlmopen_doit,
+ &dlmargs);
+ if (__builtin_expect (err_str != NULL, 0))
+ {
+ not_loaded:
+ _dl_error_printf ("\
+ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+ al->name, err_str);
+ if (malloced)
+ free ((char *) err_str);
+ }
+ else
+ {
+ struct lookup_args largs;
+ largs.name = "la_version";
+ largs.map = dlmargs.map;
+
+ /* Check whether the interface version matches. */
+ (void) _dl_catch_error (&objname, &err_str, &malloced,
+ lookup_doit, &largs);
+
+ unsigned int (*laversion) (unsigned int);
+ unsigned int lav;
+ if (err_str == NULL
+ && (laversion = largs.result) != NULL
+ && (lav = laversion (LAV_CURRENT)) > 0
+ && lav <= LAV_CURRENT)
+ {
+ /* Allocate structure for the callback function pointers.
+ This call can never fail. */
+ union
+ {
+ struct audit_ifaces ifaces;
+#define naudit_ifaces 8
+ void (*fptr[naudit_ifaces]) (void);
+ } *newp = malloc (sizeof (*newp));
+
+ /* Names of the auditing interfaces. All in one
+ long string. */
+ static const char audit_iface_names[] =
+ "la_activity\0"
+ "la_objsearch\0"
+ "la_objopen\0"
+ "la_preinit\0"
+#if __ELF_NATIVE_CLASS == 32