5f7b84
commit e621246ec6393ea08ae50310f9d5e72500f8c9bc
5f7b84
Author: Carlos O'Donell <carlos@redhat.com>
5f7b84
Date:   Mon Apr 8 17:35:05 2019 -0400
5f7b84
5f7b84
    malloc: Set and reset all hooks for tracing (Bug 16573)
5f7b84
    
5f7b84
    If an error occurs during the tracing operation, particularly during a
5f7b84
    call to lock_and_info() which calls _dl_addr, we may end up calling back
5f7b84
    into the malloc-subsystem and relock the loader lock and deadlock. For
5f7b84
    all intents and purposes the call to _dl_addr can call any of the malloc
5f7b84
    family API functions and so we should disable all tracing before calling
5f7b84
    such loader functions.  This is similar to the strategy that the new
5f7b84
    malloc tracer takes when calling the real malloc, namely that all
5f7b84
    tracing ceases at the boundary to the real function and any faults at
5f7b84
    that point are the purvue of the library (though the new tracer does
5f7b84
    this on a per-thread basis in an MT-safe fashion). Since the new tracer
5f7b84
    and the hook deprecation are not yet complete we must fix these issues
5f7b84
    where we can.
5f7b84
    
5f7b84
    Tested on x86_64 with no regressions.
5f7b84
    
5f7b84
    Co-authored-by: Kwok Cheung Yeung <kcy@codesourcery.com>
5f7b84
    Reviewed-by: DJ Delorie <dj@redhat.com>
5f7b84
5f7b84
diff --git a/malloc/mtrace.c b/malloc/mtrace.c
5f7b84
index 9064f209ec3b24c6..546d37a26018bf41 100644
5f7b84
--- a/malloc/mtrace.c
5f7b84
+++ b/malloc/mtrace.c
5f7b84
@@ -121,6 +121,41 @@ lock_and_info (const void *caller, Dl_info *mem)
5f7b84
   return res;
5f7b84
 }
5f7b84
 
5f7b84
+static void tr_freehook (void *, const void *);
5f7b84
+static void * tr_mallochook (size_t, const void *);
5f7b84
+static void * tr_reallochook (void *, size_t, const void *);
5f7b84
+static void * tr_memalignhook (size_t, size_t, const void *);
5f7b84
+
5f7b84
+/* Set all the default non-trace hooks.  */
5f7b84
+static __always_inline void
5f7b84
+set_default_hooks (void)
5f7b84
+{
5f7b84
+  __free_hook = tr_old_free_hook;
5f7b84
+  __malloc_hook = tr_old_malloc_hook;
5f7b84
+  __realloc_hook = tr_old_realloc_hook;
5f7b84
+  __memalign_hook = tr_old_memalign_hook;
5f7b84
+}
5f7b84
+
5f7b84
+/* Set all of the tracing hooks used for mtrace.  */
5f7b84
+static __always_inline void
5f7b84
+set_trace_hooks (void)
5f7b84
+{
5f7b84
+  __free_hook = tr_freehook;
5f7b84
+  __malloc_hook = tr_mallochook;
5f7b84
+  __realloc_hook = tr_reallochook;
5f7b84
+  __memalign_hook = tr_memalignhook;
5f7b84
+}
5f7b84
+
5f7b84
+/* Save the current set of hooks as the default hooks.  */
5f7b84
+static __always_inline void
5f7b84
+save_default_hooks (void)
5f7b84
+{
5f7b84
+  tr_old_free_hook = __free_hook;
5f7b84
+  tr_old_malloc_hook = __malloc_hook;
5f7b84
+  tr_old_realloc_hook = __realloc_hook;
5f7b84
+  tr_old_memalign_hook = __memalign_hook;
5f7b84
+}
5f7b84
+
5f7b84
 static void
5f7b84
 tr_freehook (void *ptr, const void *caller)
5f7b84
 {
5f7b84
@@ -138,12 +173,12 @@ tr_freehook (void *ptr, const void *caller)
5f7b84
       tr_break ();
5f7b84
       __libc_lock_lock (lock);
5f7b84
     }
5f7b84
-  __free_hook = tr_old_free_hook;
5f7b84
+  set_default_hooks ();
5f7b84
   if (tr_old_free_hook != NULL)
5f7b84
     (*tr_old_free_hook)(ptr, caller);
5f7b84
   else
5f7b84
     free (ptr);
5f7b84
-  __free_hook = tr_freehook;
5f7b84
+  set_trace_hooks ();
5f7b84
   __libc_lock_unlock (lock);
5f7b84
 }
5f7b84
 
5f7b84
@@ -155,12 +190,12 @@ tr_mallochook (size_t size, const void *caller)
5f7b84
   Dl_info mem;
5f7b84
   Dl_info *info = lock_and_info (caller, &mem;;
5f7b84
 
5f7b84
-  __malloc_hook = tr_old_malloc_hook;
5f7b84
+  set_default_hooks ();
5f7b84
   if (tr_old_malloc_hook != NULL)
5f7b84
     hdr = (void *) (*tr_old_malloc_hook)(size, caller);
5f7b84
   else
5f7b84
     hdr = (void *) malloc (size);
5f7b84
-  __malloc_hook = tr_mallochook;
5f7b84
+  set_trace_hooks ();
5f7b84
 
5f7b84
   tr_where (caller, info);
5f7b84
   /* We could be printing a NULL here; that's OK.  */
5f7b84
@@ -185,16 +220,12 @@ tr_reallochook (void *ptr, size_t size, const void *caller)
5f7b84
   Dl_info mem;
5f7b84
   Dl_info *info = lock_and_info (caller, &mem;;
5f7b84
 
5f7b84
-  __free_hook = tr_old_free_hook;
5f7b84
-  __malloc_hook = tr_old_malloc_hook;
5f7b84
-  __realloc_hook = tr_old_realloc_hook;
5f7b84
+  set_default_hooks ();
5f7b84
   if (tr_old_realloc_hook != NULL)
5f7b84
     hdr = (void *) (*tr_old_realloc_hook)(ptr, size, caller);
5f7b84
   else
5f7b84
     hdr = (void *) realloc (ptr, size);
5f7b84
-  __free_hook = tr_freehook;
5f7b84
-  __malloc_hook = tr_mallochook;
5f7b84
-  __realloc_hook = tr_reallochook;
5f7b84
+  set_trace_hooks ();
5f7b84
 
5f7b84
   tr_where (caller, info);
5f7b84
   if (hdr == NULL)
5f7b84
@@ -230,14 +261,12 @@ tr_memalignhook (size_t alignment, size_t size, const void *caller)
5f7b84
   Dl_info mem;
5f7b84
   Dl_info *info = lock_and_info (caller, &mem;;
5f7b84
 
5f7b84
-  __memalign_hook = tr_old_memalign_hook;
5f7b84
-  __malloc_hook = tr_old_malloc_hook;
5f7b84
+  set_default_hooks ();
5f7b84
   if (tr_old_memalign_hook != NULL)
5f7b84
     hdr = (void *) (*tr_old_memalign_hook)(alignment, size, caller);
5f7b84
   else
5f7b84
     hdr = (void *) memalign (alignment, size);
5f7b84
-  __memalign_hook = tr_memalignhook;
5f7b84
-  __malloc_hook = tr_mallochook;
5f7b84
+  set_trace_hooks ();
5f7b84
 
5f7b84
   tr_where (caller, info);
5f7b84
   /* We could be printing a NULL here; that's OK.  */
5f7b84
@@ -305,14 +334,8 @@ mtrace (void)
5f7b84
           malloc_trace_buffer = mtb;
5f7b84
           setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
5f7b84
           fprintf (mallstream, "= Start\n");
5f7b84
-          tr_old_free_hook = __free_hook;
5f7b84
-          __free_hook = tr_freehook;
5f7b84
-          tr_old_malloc_hook = __malloc_hook;
5f7b84
-          __malloc_hook = tr_mallochook;
5f7b84
-          tr_old_realloc_hook = __realloc_hook;
5f7b84
-          __realloc_hook = tr_reallochook;
5f7b84
-          tr_old_memalign_hook = __memalign_hook;
5f7b84
-          __memalign_hook = tr_memalignhook;
5f7b84
+	  save_default_hooks ();
5f7b84
+	  set_trace_hooks ();
5f7b84
 #ifdef _LIBC
5f7b84
           if (!added_atexit_handler)
5f7b84
             {
5f7b84
@@ -338,10 +361,7 @@ muntrace (void)
5f7b84
      file.  */
5f7b84
   FILE *f = mallstream;
5f7b84
   mallstream = NULL;
5f7b84
-  __free_hook = tr_old_free_hook;
5f7b84
-  __malloc_hook = tr_old_malloc_hook;
5f7b84
-  __realloc_hook = tr_old_realloc_hook;
5f7b84
-  __memalign_hook = tr_old_memalign_hook;
5f7b84
+  set_default_hooks ();
5f7b84
 
5f7b84
   fprintf (f, "= End\n");
5f7b84
   fclose (f);