Blob Blame History Raw
2011-02-23  Andreas Schwab  <schwab@redhat.com>

	[BZ #12509]
	* elf/dl-load.c (_dl_map_object_from_fd): Free realname before
	returning unsuccessfully.
	* elf/Makefile ($(objpfx)noload-mem): New rule.
	(noload-ENV): Define.
	(tests): Add $(objpfx)noload-mem.
	* elf/noload.c: Include <memcheck.h>.
	(main): Call mtrace.  Close all opened handles.

2010-09-27  Andreas Schwab  <schwab@redhat.com>

	* 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/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.

Index: glibc-2.12-2-gc4ccff1/elf/Makefile
===================================================================
--- glibc-2.12-2-gc4ccff1.orig/elf/Makefile
+++ glibc-2.12-2-gc4ccff1/elf/Makefile
@@ -211,7 +211,7 @@ endif
 ifeq (yesyes,$(have-fpie)$(build-shared))
 tests: $(objpfx)tst-pie1.out
 endif
-tests: $(objpfx)tst-leaks1-mem
+tests: $(objpfx)tst-leaks1-mem $(objpfx)noload-mem
 tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
@@ -664,6 +664,10 @@ $(objpfx)noload: $(objpfx)testobj1.so $(
 LDFLAGS-noload = -rdynamic
 $(objpfx)noload.out: $(objpfx)testobj5.so
 
+$(objpfx)noload-mem: $(objpfx)noload.out
+	$(common-objpfx)malloc/mtrace $(objpfx)noload.mtrace > $@
+noload-ENV = MALLOC_TRACE=$(objpfx)noload.mtrace
+
 LDFLAGS-nodelete = -rdynamic
 LDFLAGS-nodelmod1.so = -Wl,--enable-new-dtags,-z,nodelete
 LDFLAGS-nodelmod4.so = -Wl,--enable-new-dtags,-z,nodelete
Index: glibc-2.12-2-gc4ccff1/elf/dl-deps.c
===================================================================
--- glibc-2.12-2-gc4ccff1.orig/elf/dl-deps.c
+++ glibc-2.12-2-gc4ccff1/elf/dl-deps.c
@@ -478,6 +478,7 @@ _dl_map_object_deps (struct link_map *ma
 		  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.  */
@@ -662,6 +663,7 @@ Filters not supported with LD_TRACE_PREL
   l_initfini[nlist] = NULL;
   atomic_write_barrier ();
   map->l_initfini = l_initfini;
+  map->l_free_initfini = 1;
   if (l_reldeps != NULL)
     {
       atomic_write_barrier ();
Index: glibc-2.12-2-gc4ccff1/elf/dl-libc.c
===================================================================
--- glibc-2.12-2-gc4ccff1.orig/elf/dl-libc.c
+++ glibc-2.12-2-gc4ccff1/elf/dl-libc.c
@@ -250,5 +250,9 @@ 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);
       }
 }
Index: glibc-2.12-2-gc4ccff1/elf/dl-load.c
===================================================================
--- glibc-2.12-2-gc4ccff1.orig/elf/dl-load.c
+++ glibc-2.12-2-gc4ccff1/elf/dl-load.c
@@ -907,6 +907,7 @@ _dl_map_object_from_fd (const char *name
     {
       /* We are not supposed to load the object unless it is already
 	 loaded.  So return now.  */
+      free (realname);
       __close (fd);
       return NULL;
     }
@@ -925,6 +926,7 @@ _dl_map_object_from_fd (const char *name
       _dl_zerofd = _dl_sysdep_open_zero_fill ();
       if (_dl_zerofd == -1)
 	{
+	  free (realname);
 	  __close (fd);
 	  _dl_signal_error (errno, NULL, NULL,
 			    N_("cannot open zero fill device"));
Index: glibc-2.12-2-gc4ccff1/elf/noload.c
===================================================================
--- glibc-2.12-2-gc4ccff1.orig/elf/noload.c
+++ glibc-2.12-2-gc4ccff1/elf/noload.c
@@ -1,20 +1,28 @@
 #include <dlfcn.h>
 #include <stdio.h>
+#include <mcheck.h>
 
 int
 main (void)
 {
   int result = 0;
+  void *p;
+
+  mtrace ();
 
   /* First try to load an object which is a dependency.  This should
      succeed.  */
-  if (dlopen ("testobj1.so", RTLD_LAZY | RTLD_NOLOAD) == NULL)
+  p = dlopen ("testobj1.so", RTLD_LAZY | RTLD_NOLOAD);
+  if (p == NULL)
     {
       printf ("cannot open \"testobj1.so\": %s\n", dlerror ());
       result = 1;
     }
   else
-    puts ("loading \"testobj1.so\" succeeded, OK");
+    {
+      puts ("loading \"testobj1.so\" succeeded, OK");
+      dlclose (p);
+    }
 
   /* Now try loading an object which is not already loaded.  */
   if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
@@ -25,8 +33,6 @@ main (void)
   else
     {
       /* Load the object and run the same test again.  */
-      void *p;
-
       puts ("\"testobj5.so\" wasn't loaded and RTLD_NOLOAD prevented it, OK");
 
       p = dlopen ("testobj5.so", RTLD_LAZY);
@@ -41,13 +47,17 @@ main (void)
 	{
 	  puts ("loading \"testobj5.so\" succeeded, OK");
 
-	  if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) == NULL)
+	  void *q = dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD);
+	  if (q == NULL)
 	    {
 	      printf ("cannot open \"testobj5.so\": %s\n", dlerror ());
 	      result = 1;
 	    }
 	  else
-	    puts ("loading \"testobj5.so\" with RTLD_NOLOAD succeeded, OK");
+	    {
+	      puts ("loading \"testobj5.so\" with RTLD_NOLOAD succeeded, OK");
+	      dlclose (q);
+	    }
 
 	  if (dlclose (p) != 0)
 	    {
Index: glibc-2.12-2-gc4ccff1/elf/rtld.c
===================================================================
--- glibc-2.12-2-gc4ccff1.orig/elf/rtld.c
+++ glibc-2.12-2-gc4ccff1/elf/rtld.c
@@ -2249,6 +2249,7 @@ ERROR: ld.so: object '%s' cannot be load
 	      lnp->dont_free = 1;
 	      lnp = lnp->next;
 	    }
+	  l->l_free_initfini = 0;
 
 	  if (l != &GL(dl_rtld_map))
 	    _dl_relocate_object (l, l->l_scope, GLRO(dl_lazy) ? RTLD_LAZY : 0,
Index: glibc-2.12-2-gc4ccff1/include/link.h
===================================================================
--- glibc-2.12-2-gc4ccff1.orig/include/link.h
+++ glibc-2.12-2-gc4ccff1/include/link.h
@@ -192,6 +192,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;