about summary refs log tree commit diff
path: root/elf/rtld.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/rtld.c')
-rw-r--r--elf/rtld.c124
1 files changed, 92 insertions, 32 deletions
diff --git a/elf/rtld.c b/elf/rtld.c
index 39435f8243..f9a2cd3d03 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -44,6 +44,10 @@ extern void *_dl_sysdep_read_whole_file (const char *filename,
 					 size_t *filesize_ptr,
 					 int mmap_prot);
 
+/* Helper function to handle errors while resolving symbols.  */
+static void print_unresolved (const char *errstring, const char *objname);
+
+
 int _dl_argc;
 char **_dl_argv;
 const char *_dl_rpath;
@@ -142,11 +146,19 @@ dl_main (const ElfW(Phdr) *phdr,
   enum { normal, list, verify, trace } mode;
   struct link_map **preloads;
   unsigned int npreloads;
+  const char *preloadlist;
   size_t file_size;
   char *file;
 
   mode = getenv ("LD_TRACE_LOADED_OBJECTS") != NULL ? trace : normal;
 
+  /* LAZY is determined by the parameters --datadeps and --function-deps
+     if we trace the binary.  */
+  if (mode == trace)
+    lazy = -1;
+  else
+    lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
+
   /* Set up a flag which tells we are just starting.  */
   _dl_starting_up = 1;
 
@@ -186,22 +198,44 @@ of this helper program; chances are you did not intend to run this program.\n",
       /* Note the place where the dynamic linker actually came from.  */
       _dl_rtld_map.l_name = _dl_argv[0];
 
-      if (! strcmp (_dl_argv[1], "--list"))
-	{
-	  mode = list;
+      while (_dl_argc > 1)
+	if (! strcmp (_dl_argv[1], "--list"))
+	  {
+	    mode = list;
+	    lazy = -1;	/* This means do no dependency analysis.  */
 
-	  ++_dl_skip_args;
-	  --_dl_argc;
-	  ++_dl_argv;
-	}
-      else if (! strcmp (_dl_argv[1], "--verify"))
-	{
-	  mode = verify;
+	    ++_dl_skip_args;
+	    --_dl_argc;
+	    ++_dl_argv;
+	  }
+	else if (! strcmp (_dl_argv[1], "--verify"))
+	  {
+	    mode = verify;
 
-	  ++_dl_skip_args;
-	  --_dl_argc;
-	  ++_dl_argv;
-	}
+	    ++_dl_skip_args;
+	    --_dl_argc;
+	    ++_dl_argv;
+	  }
+	else if (! strcmp (_dl_argv[1], "--data-relocs"))
+	  {
+	    mode = trace;
+	    lazy = 1;	/* This means do only data relocation analysis.  */
+
+	    ++_dl_skip_args;
+	    --_dl_argc;
+	    ++_dl_argv;
+	  }
+	else if (! strcmp (_dl_argv[1], "--function-relocs"))
+	  {
+	    mode = trace;
+	    lazy = 0;	/* This means do also function relocation analysis.  */
+
+	    ++_dl_skip_args;
+	    --_dl_argc;
+	    ++_dl_argv;
+	  }
+	else
+	  break;
 
       ++_dl_skip_args;
       --_dl_argc;
@@ -311,23 +345,22 @@ of this helper program; chances are you did not intend to run this program.\n",
   preloads = NULL;
   npreloads = 0;
 
-  if (! __libc_enable_secure)
+  preloadlist = getenv ("LD_PRELOAD");
+  if (preloadlist)
     {
-      const char *preloadlist = getenv ("LD_PRELOAD");
-      if (preloadlist)
-	{
-	  /* The LD_PRELOAD environment variable gives a white space
-	     separated list of libraries that are loaded before the
-	     executable's dependencies and prepended to the global
-	     scope list.  */
-	  char *list = strdupa (preloadlist);
-	  char *p;
-	  while ((p = strsep (&list, " ")) != NULL)
-	    {
-	      (void) _dl_map_object (NULL, p, lt_library, 0);
-	      ++npreloads;
-	    }
-	}
+      /* The LD_PRELOAD environment variable gives a white space
+	 separated list of libraries that are loaded before the
+	 executable's dependencies and prepended to the global scope
+	 list.  If the binary is running setuid all elements
+	 containing a '/' are ignored since it is insecure.  */
+      char *list = strdupa (preloadlist);
+      char *p;
+      while ((p = strsep (&list, " ")) != NULL)
+	if (! __libc_enable_secure || strchr (p, '/') == NULL)
+	  {
+	    (void) _dl_map_object (NULL, p, lt_library, 0);
+	    ++npreloads;
+	  }
     }
 
   /* Read the contents of the file.  */
@@ -496,12 +529,31 @@ of this helper program; chances are you did not intend to run this program.\n",
 	      *--bp = '0';
 	    _dl_sysdep_message (" in object at 0x", bp, "\n", NULL);
 	  }
+      else if (lazy >= 0)
+	{
+	  /* We have to do symbol dependency testing.  */
+	  void doit (void)
+	    {
+	      _dl_relocate_object (l, _dl_object_relocation_scope (l), lazy);
+	    }
+
+	  l = _dl_loaded;
+	  while (l->l_next)
+	    l = l->l_next;
+	  do
+	    {
+	      if (l != &_dl_rtld_map && l->l_opencount > 0)
+		{
+		  _dl_receive_error (print_unresolved, doit);
+		  *_dl_global_scope_end = NULL;
+		}
+	      l = l->l_prev;
+	    } while (l);
+	}
 
       _exit (0);
     }
 
-  lazy = !__libc_enable_secure && *(getenv ("LD_BIND_NOW") ?: "") == '\0';
-
   {
     /* Now we have all the objects loaded.  Relocate them all except for
        the dynamic linker itself.  We do this in reverse order so that copy
@@ -573,3 +625,11 @@ of this helper program; chances are you did not intend to run this program.\n",
   /* Once we return, _dl_sysdep_start will invoke
      the DT_INIT functions and then *USER_ENTRY.  */
 }
+
+/* This is a little helper function for resolving symbols while
+   tracing the binary.  */
+static void
+print_unresolved (const char *errstring, const char *objname)
+{
+  _dl_sysdep_error (errstring, "	(", objname, ")\n", NULL);
+}