This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

dlfcn/failtest crash



After configuring glibc-2000-08-26 with a --prefix, but before doing
"make install", "make check" fails: dlfcn/failtest dumps core.

Here is the relevant output:

$ /packages/glibc-20000826-build/elf/ld-linux.so.2 --library-path /packages/glibc-20000826-build:/packages/glibc-20000826-build/math:/packages/glibc-20000826-build/elf:/packages/glibc-20000826-build/dlfcn:/packages/glibc-20000826-build/nss:/packages/glibc-20000826-build/nis:/packages/glibc-20000826-build/rt:/packages/glibc-20000826-build/resolv:/packages/glibc-20000826-build/crypt:/packages/glibc-20000826-build/linuxthreads /packages/glibc-20000826-build/dlfcn/failtest
Round 0: Try loading "a-file-with-this-name-does-not-exist"
Speicherzugriffsfehler (core dumped)

The gdb I have doesn't understand the core dump, but it can produce a
backtrace of the process at the fault location:

(gdb) where
#0  0x40073dc4 in ?? ()
#1  0x40073d5f in ?? ()
#2  0x800076b5 in ?? ()
#3  0x80007be5 in ?? ()
#4  0x400f3600 in ?? ()
#5  0x8000d012 in ?? ()
#6  0x400f396e in ?? ()
#7  0x40001334 in ?? ()
#8  0x8000d012 in ?? ()
#9  0x40001762 in ?? ()
#10 0x40001373 in ?? ()
#11 0x80485ca in ?? ()
#12 0x4001f964 in ?? ()

You want a more reasonable backtrace? Here it is:

       eip     funcstart    lib          source                  func

#0  0x40073dc4 0x40073d90 libc.so     malloc/malloc.c:3071     chunk_free
#1  0x40073d5f 0x40073cd0 libc.so     malloc/malloc.c:3043     __libc_free
#2  0x800076b5 0x80007410 ld.so       elf/dl-load.c:1328       open_path
#3  0x80007be5 0x800076d0 ld.so       elf/dl-load.c:1522       _dl_map_object
#4  0x400f3600 0x400f3450 libc.so     elf/dl-open.c:148        dl_open_worker
#5  0x8000d012 0x8000cf60 ld.so       elf/dl-error.c:138       _dl_catch_error
#6  0x400f396e 0x400f38f0 libc.so     elf/dl-open.c:327        _dl_open
#7  0x40001334 0x40001300 libdl.so    dlfcn/dlopen.c:39        dlopen_doit
#8  0x8000d012 0x8000cf60 ld.so       elf/dl-error.c:138       _dl_catch_error
#9  0x40001762 0x40001630 libdl.so    dlfcn/dlerror.c:132      _dlerror_run
#10 0x40001373 0x40001340 libdl.so    dlfcn/dlopen.c:52        dlopen
#11  0x80485ca  0x8048580 failtest    dlfcn/failtest.c:26      main
#12 0x4001f964            libc.so

The *dirsp argument passed to free() in elf/dl-load.c:1328 is
= rtld_search_dirs = 0x80017400, and one can see from the memory map
that it was allocated by the bootstrap malloc() in elf/dl-minimal.c
and therefore must not be passed to free().
Otherwise free(0x80017400) -> chunk_free(0x464c457f, 0x800173f8) -> boom.

08048000-08049000 r-xp 00000000 /packages/glibc-20000826-build/dlfcn/failtest
08049000-0804a000 rw-p 00000000 /packages/glibc-20000826-build/dlfcn/failtest
40000000-40002000 r-xp 00000000 /packages/glibc-20000826-build/dlfcn/libdl.so
40002000-40003000 rw-p 00001000 /packages/glibc-20000826-build/dlfcn/libdl.so
40003000-40104000 r-xp 00000000 /packages/glibc-20000826-build/libc.so
40104000-4010a000 rw-p 00100000 /packages/glibc-20000826-build/libc.so
4010a000-4010f000 rw-p 00000000 mmap (libc.so bss segment)
80000000-80016000 r-xp 00000000 /packages/glibc-20000826-build/elf/ld.so
80016000-80017000 rw-p 00015000 /packages/glibc-20000826-build/elf/ld.so
80017000-80018000 rwxp 00000000 mmap (minimal malloc)
bfffc000-c0000000 rwxp ffffd000 stack

Here is a patch which does two things:

- Before the open_path(...&rtld_search_dirs...) call, test whether
  rtld_search_dirs has been set to empty. This is needed regardless how
  the malloc/free problem is solved; otherwise failtest crashes during
  the second loop round (out of 10).

- Changes open_path so that it calls free() only if *dirsp has been
  allocated by a decompose_rpath call immediately before. In all other
  cases, it is not clear which malloc() allocated it (the current one or
  the minimal one), therefore a memory leak is preferred to a crash.

To really fix the memory leaks here, a different idea would be to
store in each "struct r_search_path_elem **" a bit telling with which
memory allocator it has been allocated.

Bruno


2000-08-27  Bruno Haible  <haible@clisp.cons.org>

	* elf/dl-load.c (open_path): Add a argument telling whether *dirsp
	is guaranteed to be allocated with the same malloc() and may be
	passed to free().
	(_dl_map_object): Update open_path calls. If rtld_search_dirs has
	been set to empty by an earlier open_path call, don't pass it again.

*** glibc-20000826/elf/dl-load.c.bak	Fri Aug 25 23:52:56 2000
--- glibc-20000826/elf/dl-load.c	Sun Aug 27 02:49:08 2000
***************
*** 1204,1216 ****
      _dl_debug_message (0, "\t\t(", what, ")\n", NULL);
  }
  
! /* Try to open NAME in one of the directories in DIRS.
     Return the fd, or -1.  If successful, fill in *REALNAME
!    with the malloc'd full directory name.  */
  
  static int
  open_path (const char *name, size_t namelen, int preloaded,
! 	   struct r_search_path_elem ***dirsp,
  	   char **realname)
  {
    struct r_search_path_elem **dirs = *dirsp;
--- 1204,1219 ----
      _dl_debug_message (0, "\t\t(", what, ")\n", NULL);
  }
  
! /* Try to open NAME in one of the directories in *DIRSP.
     Return the fd, or -1.  If successful, fill in *REALNAME
!    with the malloc'd full directory name.  If it turns out
!    that none of the directories in *DIRSP exists, *DIRSP is
!    replaced with (void *) -1, and the old value is free()d
!    if MAY_FREE_DIRS is true.  */
  
  static int
  open_path (const char *name, size_t namelen, int preloaded,
! 	   struct r_search_path_elem ***dirsp, int may_free_dirs,
  	   char **realname)
  {
    struct r_search_path_elem **dirs = *dirsp;
***************
*** 1325,1331 ****
    /* Remove the whole path if none of the directories exists.  */
    if (! any)
      {
!       free (*dirsp);
        *dirsp = (void *) -1;
      }
  
--- 1328,1337 ----
    /* Remove the whole path if none of the directories exists.  */
    if (! any)
      {
!       /* Paths which were allocated using the minimal malloc() in ld.so
! 	 must not be freed using the general free() in libc.  */
!       if (may_free_dirs)
! 	free (*dirsp);
        *dirsp = (void *) -1;
      }
  
***************
*** 1414,1425 ****
  
  		      if (l->l_rpath_dirs != (void *) -1)
  			fd = open_path (name, namelen, preloaded,
! 					&l->l_rpath_dirs, &realname);
  		    }
  		}
  	      else if (l->l_rpath_dirs != (void *) -1)
  		fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
! 				&realname);
  	    }
  
  	  /* If dynamically linked, try the DT_RPATH of the executable
--- 1420,1431 ----
  
  		      if (l->l_rpath_dirs != (void *) -1)
  			fd = open_path (name, namelen, preloaded,
! 					&l->l_rpath_dirs, 1, &realname);
  		    }
  		}
  	      else if (l->l_rpath_dirs != (void *) -1)
  		fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
! 				0, &realname);
  	    }
  
  	  /* If dynamically linked, try the DT_RPATH of the executable
***************
*** 1427,1439 ****
  	  l = _dl_loaded;
  	  if (fd == -1 && l && l->l_type != lt_loaded && l != loader
  	      && l->l_rpath_dirs != (void *) -1)
! 	    fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs,
  			    &realname);
  	}
  
        /* Try the LD_LIBRARY_PATH environment variable.  */
        if (fd == -1 && env_path_list != (void *) -1)
! 	fd = open_path (name, namelen, preloaded, &env_path_list, &realname);
  
        /* Look at the RUNPATH informaiton for this binary.  */
        if (loader != NULL && loader->l_runpath_dirs != (void *) -1)
--- 1433,1446 ----
  	  l = _dl_loaded;
  	  if (fd == -1 && l && l->l_type != lt_loaded && l != loader
  	      && l->l_rpath_dirs != (void *) -1)
! 	    fd = open_path (name, namelen, preloaded, &l->l_rpath_dirs, 0,
  			    &realname);
  	}
  
        /* Try the LD_LIBRARY_PATH environment variable.  */
        if (fd == -1 && env_path_list != (void *) -1)
! 	fd = open_path (name, namelen, preloaded, &env_path_list, 0,
! 			&realname);
  
        /* Look at the RUNPATH informaiton for this binary.  */
        if (loader != NULL && loader->l_runpath_dirs != (void *) -1)
***************
*** 1453,1464 ****
  
  		  if (loader->l_runpath_dirs != (void *) -1)
  		    fd = open_path (name, namelen, preloaded,
! 				    &loader->l_runpath_dirs, &realname);
  		}
  	    }
  	  else if (loader->l_runpath_dirs != (void *) -1)
  	    fd = open_path (name, namelen, preloaded,
! 			    &loader->l_runpath_dirs, &realname);
  	}
  
        if (fd == -1)
--- 1460,1471 ----
  
  		  if (loader->l_runpath_dirs != (void *) -1)
  		    fd = open_path (name, namelen, preloaded,
! 				    &loader->l_runpath_dirs, 1, &realname);
  		}
  	    }
  	  else if (loader->l_runpath_dirs != (void *) -1)
  	    fd = open_path (name, namelen, preloaded,
! 			    &loader->l_runpath_dirs, 0, &realname);
  	}
  
        if (fd == -1)
***************
*** 1518,1525 ****
        /* Finally, try the default path.  */
        if (fd == -1
  	  && (l == NULL ||
! 	      __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1)))
! 	fd = open_path (name, namelen, preloaded, &rtld_search_dirs,
  			&realname);
  
        /* Add another newline when we a tracing the library loading.  */
--- 1525,1533 ----
        /* Finally, try the default path.  */
        if (fd == -1
  	  && (l == NULL ||
! 	      __builtin_expect (!(l->l_flags_1 & DF_1_NODEFLIB), 1))
! 	  && rtld_search_dirs != (void *) -1)
! 	fd = open_path (name, namelen, preloaded, &rtld_search_dirs, 0,
  			&realname);
  
        /* Add another newline when we a tracing the library loading.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]