about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog26
-rw-r--r--elf/rtld.c21
-rw-r--r--malloc/malloc.c63
-rw-r--r--sysdeps/unix/sysv/linux/i386/dl-librecon.h3
4 files changed, 86 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 01737dfeec..5dd30e6129 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,30 @@
+1999-02-23  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>
+
+	* malloc/malloc.c (mALLOC_SET_STATe): Handle the case where a
+	non-checked heap is restored when malloc checking was requested by
+	the user.
+	(struct malloc_state): Add using_malloc_checking.
+	(MALLOC_STATE_VERSION): Increment minor.
+	(using_malloc_checking, disallow_malloc_check): New variables.
+	(__malloc_check_init): Use them.
+	(mALLOC_GET_STATe): Use mALLOc to allocate the malloc_state, so
+	that it can the chunk is properly instrumented when malloc
+	checking is enabled.  Set the new using_malloc_checking field.
+	(malloc_hook_ini): Correct signature when _LIBC is not defined.
+
+1999-02-23  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>
+
+	* sysdeps/unix/sysv/linux/i386/dl-librecon.h
+	(DISTINGUISH_LIB_VERSIONS): Don't relocate DT_STRTAB a second
+	time.
+
+	* elf/rtld.c (dl_main): Rename paths_initialized to rtld_is_main.
+	Don't call elf_get_dynamic_info and _dl_setup_hash a second time
+	if ld.so is the main program.
+
 1999-02-23  Ulrich Drepper  <drepper@cygnus.com>
 
-	* stdio-common/vfprintf.c (vfprintf): If precision or width if too
+	* stdio-common/vfprintf.c (vfprintf): If precision or width is too
 	large for work_buffer, allocate new buffer.
 	(printf_unknown): Likewise.  [PR libc/988]
 
diff --git a/elf/rtld.c b/elf/rtld.c
index 762cdc5ff2..40405d15af 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -340,7 +340,7 @@ dl_main (const ElfW(Phdr) *phdr,
   char *file;
   int has_interp = 0;
   unsigned int i;
-  int paths_initialized = 0;
+  int rtld_is_main = 0;
   hp_timing_t start;
   hp_timing_t stop;
   hp_timing_t diff;
@@ -368,6 +368,7 @@ dl_main (const ElfW(Phdr) *phdr,
 	 pay attention to its PT_INTERP command (we are the interpreter
 	 ourselves).  This is an easy way to test a new ld.so before
 	 installing it.  */
+      rtld_is_main = 1;
 
       /* Note the place where the dynamic linker actually came from.  */
       _dl_rtld_map.l_name = _dl_argv[0];
@@ -441,7 +442,6 @@ of this helper program; chances are you did not intend to run this program.\n\
       /* Initialize the data structures for the search paths for shared
 	 objects.  */
       _dl_init_paths (library_path);
-      paths_initialized = 1;
 
       if (__builtin_expect (mode, normal) == verify)
 	{
@@ -574,12 +574,15 @@ of this helper program; chances are you did not intend to run this program.\n\
   else
     assert (_dl_rtld_map.l_libname); /* How else did we get here?  */
 
-  /* Extract the contents of the dynamic section for easy access.  */
-  elf_get_dynamic_info (_dl_loaded->l_ld, _dl_loaded->l_addr,
-			_dl_loaded->l_info);
-  if (_dl_loaded->l_info[DT_HASH])
-    /* Set up our cache of pointers into the hash table.  */
-    _dl_setup_hash (_dl_loaded);
+  if (! rtld_is_main)
+    {
+      /* Extract the contents of the dynamic section for easy access.  */
+      elf_get_dynamic_info (_dl_loaded->l_ld, _dl_loaded->l_addr,
+			    _dl_loaded->l_info);
+      if (_dl_loaded->l_info[DT_HASH])
+	/* Set up our cache of pointers into the hash table.  */
+	_dl_setup_hash (_dl_loaded);
+    }
 
   if (__builtin_expect (mode, normal) == verify)
     {
@@ -597,7 +600,7 @@ of this helper program; chances are you did not intend to run this program.\n\
       _exit (has_interp ? 0 : 2);
     }
 
-  if (! paths_initialized)
+  if (! rtld_is_main)
     /* Initialize the data structures for the search paths for shared
        objects.  */
     _dl_init_paths (library_path);
diff --git a/malloc/malloc.c b/malloc/malloc.c
index 2cf2025237..03d68b75e7 100644
--- a/malloc/malloc.c
+++ b/malloc/malloc.c
@@ -1691,14 +1691,11 @@ thread_atfork_static(ptmalloc_lock_all, ptmalloc_unlock_all, \
    initialization routine, then do the normal work. */
 
 static Void_t*
-#ifdef _LIBC
-malloc_hook_ini(size_t sz, const __malloc_ptr_t caller)
-#else
 #if __STD_C
-malloc_hook_ini(size_t sz)
+malloc_hook_ini(size_t sz, const __malloc_ptr_t caller)
 #else
-malloc_hook_ini(sz) size_t sz;
-#endif
+malloc_hook_ini(sz, caller)
+     size_t sz; const __malloc_ptr_t caller;
 #endif
 {
   __malloc_hook = NULL;
@@ -1746,10 +1743,33 @@ __malloc_ptr_t weak_variable (*__memalign_hook)
      = memalign_hook_ini;
 void weak_variable (*__after_morecore_hook) __MALLOC_P ((void)) = NULL;
 
+/* Whether we are using malloc checking.  */
+static int using_malloc_checking;
+
+/* A flag that is set by malloc_set_state, to signal that malloc checking
+   must not be enabled on the request from the user (via the MALLOC_CHECK_
+   environment variable).  It is reset by __malloc_check_init to tell
+   malloc_set_state that the user has requested malloc checking.
+
+   The purpose of this flag is to make sure that malloc checking is not
+   enabled when the heap to be restored was constructed without malloc
+   checking, and thus does not contain the required magic bytes.
+   Otherwise the heap would be corrupted by calls to free and realloc.  If
+   it turns out that the heap was created with malloc checking and the
+   user has requested it malloc_set_state just calls __malloc_check_init
+   again to enable it.  On the other hand, reusing such a heap without
+   further malloc checking is safe.  */
+static int disallow_malloc_check;
+
 /* Activate a standard set of debugging hooks. */
 void
 __malloc_check_init()
 {
+  if (disallow_malloc_check) {
+    disallow_malloc_check = 0;
+    return;
+  }
+  using_malloc_checking = 1;
   __malloc_hook = malloc_check;
   __free_hook = free_check;
   __realloc_hook = realloc_check;
@@ -4041,7 +4061,7 @@ int mALLOPt(param_number, value) int param_number; int value;
    functions. */
 
 #define MALLOC_STATE_MAGIC   0x444c4541l
-#define MALLOC_STATE_VERSION (0*0x100l + 0l) /* major*0x100 + minor */
+#define MALLOC_STATE_VERSION (0*0x100l + 1l) /* major*0x100 + minor */
 
 struct malloc_state {
   long          magic;
@@ -4060,24 +4080,20 @@ struct malloc_state {
   unsigned int  max_n_mmaps;
   unsigned long mmapped_mem;
   unsigned long max_mmapped_mem;
+  int		using_malloc_checking;
 };
 
 Void_t*
 mALLOC_GET_STATe()
 {
-  mchunkptr victim;
   struct malloc_state* ms;
   int i;
   mbinptr b;
 
-  ptmalloc_init();
-  (void)mutex_lock(&main_arena.mutex);
-  victim = chunk_alloc(&main_arena, request2size(sizeof(*ms)));
-  if(!victim) {
-    (void)mutex_unlock(&main_arena.mutex);
+  ms = (struct malloc_state*)mALLOc(sizeof(*ms));
+  if (!ms)
     return 0;
-  }
-  ms = (struct malloc_state*)chunk2mem(victim);
+  (void)mutex_lock(&main_arena.mutex);
   ms->magic = MALLOC_STATE_MAGIC;
   ms->version = MALLOC_STATE_VERSION;
   ms->av[0] = main_arena.av[0];
@@ -4108,6 +4124,11 @@ mALLOC_GET_STATe()
   ms->max_n_mmaps = max_n_mmaps;
   ms->mmapped_mem = mmapped_mem;
   ms->max_mmapped_mem = max_mmapped_mem;
+#if defined _LIBC || defined MALLOC_HOOKS
+  ms->using_malloc_checking = using_malloc_checking;
+#else
+  ms->using_malloc_checking = 0;
+#endif
   (void)mutex_unlock(&main_arena.mutex);
   return (Void_t*)ms;
 }
@@ -4123,6 +4144,9 @@ mALLOC_SET_STATe(msptr) Void_t* msptr;
   int i;
   mbinptr b;
 
+#if defined _LIBC || defined MALLOC_HOOKS
+  disallow_malloc_check = 1;
+#endif
   ptmalloc_init();
   if(ms->magic != MALLOC_STATE_MAGIC) return -1;
   /* Must fail if the major version is too high. */
@@ -4160,6 +4184,15 @@ mALLOC_SET_STATe(msptr) Void_t* msptr;
   mmapped_mem = ms->mmapped_mem;
   max_mmapped_mem = ms->max_mmapped_mem;
   /* add version-dependent code here */
+  if (ms->version >= 1) {
+#if defined _LIBC || defined MALLOC_HOOKS
+    /* Check whether it is safe to enable malloc checking.  */
+    if (ms->using_malloc_checking && !using_malloc_checking &&
+	!disallow_malloc_check)
+      __malloc_check_init ();
+#endif
+  }
+
   (void)mutex_unlock(&main_arena.mutex);
   return 0;
 }
diff --git a/sysdeps/unix/sysv/linux/i386/dl-librecon.h b/sysdeps/unix/sysv/linux/i386/dl-librecon.h
index 4ae2e87a7b..84b4396285 100644
--- a/sysdeps/unix/sysv/linux/i386/dl-librecon.h
+++ b/sysdeps/unix/sysv/linux/i386/dl-librecon.h
@@ -33,8 +33,7 @@
 	  const ElfW(Dyn) *d;						      \
 	  const char *strtab;						      \
 									      \
-	  strtab = ((void *) _dl_loaded->l_addr				      \
-		    + _dl_loaded->l_info[DT_STRTAB]->d_un.d_ptr);	      \
+	  strtab = (const char *) _dl_loaded->l_info[DT_STRTAB]->d_un.d_ptr;  \
 									      \
 	  for (d = _dl_loaded->l_ld; d->d_tag != DT_NULL; ++d)		      \
 	    if (d->d_tag == DT_NEEDED					      \