about summary refs log tree commit diff
path: root/elf/dl-load.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r--elf/dl-load.c152
1 files changed, 137 insertions, 15 deletions
diff --git a/elf/dl-load.c b/elf/dl-load.c
index eb1a7919fb..7f11b62bf4 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -827,6 +827,8 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
   /* Initialize to keep the compiler happy.  */
   const char *errstring = NULL;
   int errval = 0;
+  struct r_debug *r = _dl_debug_initialize (0);
+  bool make_consistent = false;
 
   /* Get file information.  */
   if (__builtin_expect (__fxstat64 (_STAT_VER, fd, &st) < 0, 0))
@@ -835,6 +837,12 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
     call_lose_errno:
       errval = errno;
     call_lose:
+      if (make_consistent)
+	{
+	  r->r_state = RT_CONSISTENT;
+	  _dl_debug_state ();
+	}
+
       lose (errval, fd, name, realname, l, errstring);
     }
 
@@ -905,6 +913,39 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
     }
 #endif
 
+  /* Signal that we are going to add new objects.  */
+  if (r->r_state == RT_CONSISTENT)
+    {
+#ifdef SHARED
+      /* Auditing checkpoint: we are going to add new objects.  */
+      if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+	{
+	  struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
+	  /* Do not call the functions for any auditing object.  */
+	  if (head->l_auditing == 0)
+	    {
+	      struct audit_ifaces *afct = GLRO(dl_audit);
+	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+		{
+		  if (afct->activity != NULL)
+		    afct->activity (&head->l_audit[cnt].cookie, LA_ACT_ADD);
+
+		  afct = afct->next;
+		}
+	    }
+	}
+#endif
+
+      /* Notify the debugger we have added some objects.  We need to
+	 call _dl_debug_initialize in a static program in case dynamic
+	 linking has not been used before.  */
+      r->r_state = RT_ADD;
+      _dl_debug_state ();
+      make_consistent = true;
+    }
+  else
+    assert (r->r_state == RT_ADD);
+
   /* Enter the new object in the list of loaded objects.  */
   l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
   if (__builtin_expect (l == NULL, 0))
@@ -1044,7 +1085,7 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp,
 	    }
 
 # ifdef SHARED
-	  if (l->l_prev == NULL)
+	  if (l->l_prev == NULL || (mode && __RTLD_AUDIT) != 0)
 	    /* We are loading the executable itself when the dynamic linker
 	       was executed directly.  The setup will happen later.  */
 	    break;
@@ -1424,6 +1465,26 @@ cannot enable executable stack as shared object requires");
     add_name_to_object (l, ((const char *) D_PTR (l, l_info[DT_STRTAB])
 			    + l->l_info[DT_SONAME]->d_un.d_val));
 
+#ifdef SHARED
+  /* Auditing checkpoint: we have a new object.  */
+  if (__builtin_expect (GLRO(dl_naudit) > 0, 0))
+    {
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->objopen != NULL)
+	    {
+	      l->l_audit[cnt].bindflags
+		= afct->objopen (l, nsid, &l->l_audit[cnt].cookie);
+
+	      l->l_audit_any_plt |= l->l_audit[cnt].bindflags != 0;
+	    }
+
+	  afct = afct->next;
+	}
+    }
+#endif
+
   return l;
 }
 
@@ -1471,7 +1532,8 @@ print_search_path (struct r_search_path_elem **list,
    this could mean there is something wrong in the installation and the
    user might want to know about this.  */
 static int
-open_verify (const char *name, struct filebuf *fbp)
+open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
+	     int whatcode)
 {
   /* This is the expected ELF header.  */
 #define ELF32_CLASS ELFCLASS32
@@ -1500,13 +1562,34 @@ open_verify (const char *name, struct filebuf *fbp)
     ElfW(Word) type;
     char vendor[4];
   } expected_note = { 4, 16, 1, "GNU" };
-  int fd;
   /* Initialize it to make the compiler happy.  */
   const char *errstring = NULL;
   int errval = 0;
 
+#ifdef SHARED
+  /* Give the auditing libraries a chance.  */
+  if (__builtin_expect (GLRO(dl_naudit) > 0, 0) && whatcode != 0
+      && loader->l_auditing == 0)
+    {
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->objsearch != NULL)
+	    {
+	      name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
+				      whatcode);
+	      if (name == NULL)
+		/* Ignore the path.  */
+		return -1;
+	    }
+
+	  afct = afct->next;
+	}
+    }
+#endif
+
   /* Open the file.  We always open files read-only.  */
-  fd = __open (name, O_RDONLY);
+  int fd = __open (name, O_RDONLY);
   if (fd != -1)
     {
       ElfW(Ehdr) *ehdr;
@@ -1664,7 +1747,7 @@ open_verify (const char *name, struct filebuf *fbp)
 static int
 open_path (const char *name, size_t namelen, int preloaded,
 	   struct r_search_path_struct *sps, char **realname,
-	   struct filebuf *fbp)
+	   struct filebuf *fbp, struct link_map *loader, int whatcode)
 {
   struct r_search_path_elem **dirs = sps->dirs;
   char *buf;
@@ -1708,12 +1791,16 @@ open_path (const char *name, size_t namelen, int preloaded,
 	  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
 	    _dl_debug_printf ("  trying file=%s\n", buf);
 
-	  fd = open_verify (buf, fbp);
+	  fd = open_verify (buf, fbp, loader, whatcode);
 	  if (this_dir->status[cnt] == unknown)
 	    {
 	      if (fd != -1)
 		this_dir->status[cnt] = existing;
-	      else
+	      /* Do not update the directory information when loading
+		 auditing code.  We must try to disturb the program as
+		 little as possible.  */
+	      else if (loader == NULL
+		       || GL(dl_ns)[loader->l_ns]._ns_loaded->l_audit == 0)
 		{
 		  /* We failed to open machine dependent library.  Let's
 		     test whether there is any directory at all.  */
@@ -1731,7 +1818,7 @@ open_path (const char *name, size_t namelen, int preloaded,
 	    }
 
 	  /* Remember whether we found any existing directory.  */
-	  here_any |= this_dir->status[cnt] == existing;
+	  here_any |= this_dir->status[cnt] != nonexisting;
 
 	  if (fd != -1 && __builtin_expect (preloaded, 0)
 	      && INTUSE(__libc_enable_secure))
@@ -1847,6 +1934,32 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 			      loader->l_name[0]
 			      ? loader->l_name : rtld_progname, loader->l_ns);
 
+#ifdef SHARED
+  /* Give the auditing libraries a chance to change the name before we
+     try anything.  */
+  if (__builtin_expect (GLRO(dl_naudit) > 0, 0)
+      && (loader == NULL || loader->l_auditing == 0))
+    {
+      struct audit_ifaces *afct = GLRO(dl_audit);
+      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+	{
+	  if (afct->objsearch != NULL)
+	    {
+	      name = afct->objsearch (name, &loader->l_audit[cnt].cookie,
+				      LA_SER_ORIG);
+	      if (name == NULL)
+		{
+		  /* Do not try anything further.  */
+		  fd = -1;
+		  goto no_file;
+		}
+	    }
+
+	  afct = afct->next;
+	}
+    }
+#endif
+
   if (strchr (name, '/') == NULL)
     {
       /* Search for NAME in several places.  */
@@ -1867,7 +1980,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	  for (l = loader; fd == -1 && l; l = l->l_loader)
 	    if (cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
 	      fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
-			      &realname, &fb);
+			      &realname, &fb, loader, LA_SER_RUNPATH);
 
 	  /* If dynamically linked, try the DT_RPATH of the executable
              itself.  NB: we do this for lookups in any namespace.  */
@@ -1877,21 +1990,24 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	      if (l && l->l_type != lt_loaded && l != loader
 		  && cache_rpath (l, &l->l_rpath_dirs, DT_RPATH, "RPATH"))
 		fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
-				&realname, &fb);
+				&realname, &fb, loader ?: l, LA_SER_RUNPATH);
 	    }
 	}
 
       /* Try the LD_LIBRARY_PATH environment variable.  */
       if (fd == -1 && env_path_list.dirs != (void *) -1)
 	fd = open_path (name, namelen, preloaded, &env_path_list,
-			&realname, &fb);
+			&realname, &fb,
+			loader ?: GL(dl_ns)[LM_ID_BASE]._ns_loaded,
+			LA_SER_LIBPATH);
 
       /* Look at the RUNPATH information for this binary.  */
       if (fd == -1 && loader != NULL
 	  && cache_rpath (loader, &loader->l_runpath_dirs,
 			  DT_RUNPATH, "RUNPATH"))
 	fd = open_path (name, namelen, preloaded,
-			&loader->l_runpath_dirs, &realname, &fb);
+			&loader->l_runpath_dirs, &realname, &fb, loader,
+			LA_SER_RUNPATH);
 
       if (fd == -1
 	  && (__builtin_expect (! preloaded, 1)
@@ -1939,7 +2055,9 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 
 	      if (cached != NULL)
 		{
-		  fd = open_verify (cached, &fb);
+		  fd = open_verify (cached,
+				    &fb, loader ?: GL(dl_ns)[nsid]._ns_loaded,
+				    LA_SER_CONFIG);
 		  if (__builtin_expect (fd != -1, 1))
 		    {
 		      realname = local_strdup (cached);
@@ -1959,7 +2077,7 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	      || __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
 	  && rtld_search_dirs.dirs != (void *) -1)
 	fd = open_path (name, namelen, preloaded, &rtld_search_dirs,
-			&realname, &fb);
+			&realname, &fb, l, LA_SER_DEFAULT);
 
       /* Add another newline when we are tracing the library loading.  */
       if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
@@ -1975,12 +2093,16 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
 	fd = -1;
       else
 	{
-	  fd = open_verify (realname, &fb);
+	  fd = open_verify (realname, &fb,
+			    loader ?: GL(dl_ns)[nsid]._ns_loaded, 0);
 	  if (__builtin_expect (fd, 0) == -1)
 	    free (realname);
 	}
     }
 
+#ifdef SHARED
+ no_file:
+#endif
   /* In case the LOADER information has only been provided to get to
      the appropriate RUNPATH/RPATH information we do not need it
      anymore.  */