about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@redhat.com>2012-06-22 11:10:31 -0700
committerCarlos O'Donell <carlos_odonell@mentor.com>2012-06-22 11:10:31 -0700
commit0479b305c5b7c8e3fa8e3002982cf8cac02b842e (patch)
treef72a6cb6c122c086d6e7b5989e9d746c0c3431a1
parent0e3933b96344ab9c0ac633c19f4ebfdede5375d4 (diff)
downloadglibc-0479b305c5b7c8e3fa8e3002982cf8cac02b842e.tar.gz
glibc-0479b305c5b7c8e3fa8e3002982cf8cac02b842e.tar.xz
glibc-0479b305c5b7c8e3fa8e3002982cf8cac02b842e.zip
Fix invalid memory access in do_lookup_x.
[BZ #13579] Do not free l_initfini and allow it to be reused
on subsequent dl_open calls for the same library. This fixes
the invalid memory access in do_lookup_x when the previously
free'd l_initfini was accessed through l_searchlist when a
library had been opened for the second time.
-rw-r--r--ChangeLog11
-rw-r--r--NEWS25
-rw-r--r--elf/dl-close.c15
-rw-r--r--elf/dl-deps.c7
-rw-r--r--elf/dl-libc.c9
-rw-r--r--elf/rtld.c2
-rw-r--r--include/link.h8
7 files changed, 43 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog
index b7f16994d2..89997843cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-06-22  Andreas Schwab  <schwab@redhat.com>
+
+	[BZ #13579]
+	* include/link.h (struct link_map): Add l_free_initfini.
+	* elf/dl-deps.c (_dl_map_object_deps): Set it when assigning
+	l_initfini.
+	* elf/dl-close.c (_dl_close_worker): Don't free l_initfini.
+	* elf/rtld.c (dl_main): Clear it on all objects loaded on startup.
+	* elf/dl-libc.c (free_mem): Free l_initfini if l_free_initfini is
+	set.
+
 2012-06-22  Carlos O'Donell  <carlos_odonell@mentor.com>
 
 	* configure.in: Use AC_LANG_SOURCE.
diff --git a/NEWS b/NEWS
index 1ce8ee3508..a9500faeb6 100644
--- a/NEWS
+++ b/NEWS
@@ -19,18 +19,19 @@ Version 2.16
   12193, 12194, 12297, 12298, 12301, 12340, 12354, 12416, 12495, 13058,
   13223, 13361, 13525, 13526, 13527, 13528, 13529, 13530, 13531, 13532,
   13533, 13547, 13551, 13552, 13553, 13555, 13556, 13559, 13563, 13566,
-  13576, 13583, 13592, 13594, 13613, 13618, 13637, 13656, 13658, 13673,
-  13691, 13695, 13704, 13705, 13706, 13718, 13726, 13738, 13739, 13743,
-  13750, 13758, 13760, 13761, 13775, 13786, 13787, 13792, 13806, 13824,
-  13840, 13841, 13844, 13846, 13848, 13851, 13852, 13854, 13871, 13872,
-  13873, 13879, 13882, 13883, 13884, 13885, 13886, 13892, 13895, 13908,
-  13910, 13911, 13912, 13913, 13914, 13915, 13916, 13917, 13918, 13919,
-  13920, 13921, 13922, 13923, 13924, 13926, 13927, 13928, 13938, 13941,
-  13942, 13954, 13955, 13956, 13963, 13967, 13968, 13970, 13973, 13979,
-  13983, 13986, 13996, 14012, 14027, 14033, 14034, 14036, 14040, 14043,
-  14044, 14048, 14049, 14050, 14053, 14055, 14059, 14064, 14075, 14080,
-  14083, 14103, 14104, 14109, 14112, 14117, 14122, 14123, 14134, 14153,
-  14183, 14188, 14199, 14210, 14218, 14229, 14241, 14273, 14277, 14278
+  13576, 13579, 13583, 13592, 13594, 13613, 13618, 13637, 13656, 13658,
+  13673, 13691, 13695, 13704, 13705, 13706, 13718, 13726, 13738, 13739,
+  13743, 13750, 13758, 13760, 13761, 13775, 13786, 13787, 13792, 13806,
+  13824, 13840, 13841, 13844, 13846, 13848, 13851, 13852, 13854, 13871,
+  13872, 13873, 13879, 13882, 13883, 13884, 13885, 13886, 13892, 13895,
+  13908, 13910, 13911, 13912, 13913, 13914, 13915, 13916, 13917, 13918,
+  13919, 13920, 13921, 13922, 13923, 13924, 13926, 13927, 13928, 13938,
+  13941, 13942, 13954, 13955, 13956, 13963, 13967, 13968, 13970, 13973,
+  13979, 13983, 13986, 13996, 14012, 14027, 14033, 14034, 14036, 14040,
+  14043, 14044, 14048, 14049, 14050, 14053, 14055, 14059, 14064, 14075,
+  14080, 14083, 14103, 14104, 14109, 14112, 14117, 14122, 14123, 14134,
+  14153, 14183, 14188, 14199, 14210, 14218, 14229, 14241, 14273, 14277,
+  14278
 
 * Support for the x32 ABI on x86-64 added.  The x32 target is selected by
   configuring glibc with:
diff --git a/elf/dl-close.c b/elf/dl-close.c
index d232294665..a250ea5e3e 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -1,5 +1,5 @@
 /* Close a shared object opened by `_dl_open'.
-   Copyright (C) 1996-2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1996-2012 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
@@ -118,17 +118,8 @@ _dl_close_worker (struct link_map *map)
   if (map->l_direct_opencount > 0 || map->l_type != lt_loaded
       || dl_close_state != not_pending)
     {
-      if (map->l_direct_opencount == 0)
-	{
-	  if (map->l_type == lt_loaded)
-	    dl_close_state = rerun;
-	  else if (map->l_type == lt_library)
-	    {
-	      struct link_map **oldp = map->l_initfini;
-	      map->l_initfini = map->l_orig_initfini;
-	      _dl_scope_free (oldp);
-	    }
-	}
+      if (map->l_direct_opencount == 0 && map->l_type == lt_loaded)
+	dl_close_state = rerun;
 
       /* There are still references to this object.  Do nothing more.  */
       if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
index 69aec461fb..2ae496d7b5 100644
--- a/elf/dl-deps.c
+++ b/elf/dl-deps.c
@@ -1,6 +1,5 @@
 /* Load the dependencies of a mapped object.
-   Copyright (C) 1996-2003, 2004-2007, 2010-2012
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2012 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
@@ -488,6 +487,7 @@ _dl_map_object_deps (struct link_map *map,
 		  nneeded * sizeof needed[0]);
 	  atomic_write_barrier ();
 	  l->l_initfini = l_initfini;
+	  l->l_free_initfini = 1;
 	}
 
       /* If we have no auxiliary objects just go on to the next map.  */
@@ -688,6 +688,7 @@ Filters not supported with LD_TRACE_PRELINKING"));
   l_initfini[nlist] = NULL;
   atomic_write_barrier ();
   map->l_initfini = l_initfini;
+  map->l_free_initfini = 1;
   if (l_reldeps != NULL)
     {
       atomic_write_barrier ();
@@ -696,7 +697,7 @@ Filters not supported with LD_TRACE_PRELINKING"));
       _dl_scope_free (old_l_reldeps);
     }
   if (old_l_initfini != NULL)
-      map->l_orig_initfini = old_l_initfini;
+    _dl_scope_free (old_l_initfini);
 
   if (errno_reason)
     _dl_signal_error (errno_reason == -1 ? 0 : errno_reason, objname,
diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index a58e2164f6..af2e663737 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -1,6 +1,5 @@
 /* Handle loading and unloading shared objects for internal libc purposes.
-   Copyright (C) 1999-2002,2004-2006,2009,2010,2011
-   Free Software Foundation, Inc.
+   Copyright (C) 1999-2012 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Zack Weinberg <zack@rabi.columbia.edu>, 1999.
 
@@ -269,13 +268,13 @@ libc_freeres_fn (free_mem)
 
   for (Lmid_t ns = 0; ns < GL(dl_nns); ++ns)
     {
-      /* Remove all additional names added to the objects.  */
       for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
 	{
 	  struct libname_list *lnp = l->l_libname->next;
 
 	  l->l_libname->next = NULL;
 
+	  /* Remove all additional names added to the objects.  */
 	  while (lnp != NULL)
 	    {
 	      struct libname_list *old = lnp;
@@ -283,6 +282,10 @@ libc_freeres_fn (free_mem)
 	      if (! old->dont_free)
 		free (old);
 	    }
+
+	  /* Free the initfini dependency list.  */
+	  if (l->l_free_initfini)
+	    free (l->l_initfini);
 	}
 
       if (__builtin_expect (GL(dl_ns)[ns]._ns_global_scope_alloc, 0) != 0
diff --git a/elf/rtld.c b/elf/rtld.c
index a5b0ab9815..6bcf224c49 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -2292,6 +2292,8 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
 	      lnp->dont_free = 1;
 	      lnp = lnp->next;
 	    }
+	  /* Also allocated with the fake malloc().  */
+	  l->l_free_initfini = 0;
 
 	  if (l != &GL(dl_rtld_map))
 	    _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
diff --git a/include/link.h b/include/link.h
index 2eb3179475..f0c8ad521f 100644
--- a/include/link.h
+++ b/include/link.h
@@ -1,6 +1,6 @@
 /* Data structure for communication from the run-time dynamic linker for
    loaded ELF shared objects.
-   Copyright (C) 1995-2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1995-2012 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
@@ -191,6 +191,9 @@ struct link_map
 						 during LD_TRACE_PRELINKING=1
 						 contains any DT_SYMBOLIC
 						 libraries.  */
+    unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be
+				       freed, ie. not allocated with
+				       the dummy malloc in ld.so.  */
 
     /* Collected information about own RPATH directories.  */
     struct r_search_path_struct l_rpath_dirs;
@@ -239,9 +242,6 @@ struct link_map
 
     /* List of object in order of the init and fini calls.  */
     struct link_map **l_initfini;
-    /* The init and fini list generated at startup, saved when the
-       object is also loaded dynamically.  */
-    struct link_map **l_orig_initfini;
 
     /* List of the dependencies introduced through symbol binding.  */
     struct link_map_reldeps