2011-02-23 Andreas Schwab [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 . (main): Call mtrace. Close all opened handles. 2010-09-27 Andreas Schwab * 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 #include +#include 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;