1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-05 19:35:52 +03:00

Avoid potential deadlock in mtrace

The _dl_addr function might have to call malloc which would lead
to a deadlock.  Avoid by calling _dl_addr early.
This commit is contained in:
Ulrich Drepper
2011-05-16 00:58:33 -04:00
parent 6ce7537960
commit 56e5eb4619
3 changed files with 59 additions and 31 deletions

View File

@@ -1,5 +1,15 @@
2011-05-16 Ulrich Drepper <drepper@gmail.com> 2011-05-16 Ulrich Drepper <drepper@gmail.com>
[BZ #6420]
* malloc/mtrace.c (tr_where): Add additional parameter to point to
symbol info. Use it instead of calling _dl_addr locally.
(lock_and_info): New function.
(tr_freehook): Call lock_and_info and pass symbol info as additional
parameter to tr_where.
(tr_mallochook): Likewise.
(tr_reallochook): Likewise.
(tr_memalignhook): Likewise.
* malloc/mtrace.c: Remove support for USE_MTRACE_FILE. It is not * malloc/mtrace.c: Remove support for USE_MTRACE_FILE. It is not
used and couldn't be at all thread-safe. used and couldn't be at all thread-safe.

16
NEWS
View File

@@ -1,4 +1,4 @@
GNU C Library NEWS -- history of user-visible changes. 2011-5-15 GNU C Library NEWS -- history of user-visible changes. 2011-5-16
Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc. Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
See the end for copying conditions. See the end for copying conditions.
@@ -9,13 +9,13 @@ Version 2.14
* The following bugs are resolved with this release: * The following bugs are resolved with this release:
386, 7101, 9730, 9732, 9809, 10138, 10149, 10157, 11257, 11258, 11487, 386, 6420, 7101, 9730, 9732, 9809, 10138, 10149, 10157, 11257, 11258,
11532, 11578, 11653, 11668, 11724, 11901, 11945, 11947, 11952, 12052, 11487, 11532, 11578, 11653, 11668, 11724, 11901, 11945, 11947, 11952,
12083, 12158, 12178, 12200, 12346, 12393, 12420, 12432, 12445, 12449, 12052, 12083, 12158, 12178, 12200, 12346, 12393, 12420, 12432, 12445,
12453, 12454, 12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12449, 12453, 12454, 12460, 12469, 12489, 12509, 12510, 12511, 12518,
12541, 12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611, 12625, 12527, 12541, 12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611,
12626, 12631, 12650, 12653, 12655, 12660, 12681, 12685, 12711, 12713, 12625, 12626, 12631, 12650, 12653, 12655, 12660, 12681, 12685, 12711,
12714, 12717, 12723, 12724, 12734, 12738 12713, 12714, 12717, 12723, 12724, 12734, 12738
* The RPC implementation in libc is obsoleted. Old programs keep working * The RPC implementation in libc is obsoleted. Old programs keep working
but new programs cannot be linked with the routines in libc anymore. but new programs cannot be linked with the routines in libc anymore.

View File

@@ -79,46 +79,59 @@ tr_break ()
} }
libc_hidden_def (tr_break) libc_hidden_def (tr_break)
static void tr_where (const __ptr_t) __THROW internal_function; static void tr_where (const __ptr_t, Dl_info *) __THROW internal_function;
static void static void
internal_function internal_function
tr_where (caller) tr_where (caller, info)
const __ptr_t caller; const __ptr_t caller;
Dl_info *info;
{ {
if (caller != NULL) if (caller != NULL)
{ {
#ifdef HAVE_ELF if (info != NULL)
Dl_info info;
if (_dl_addr (caller, &info, NULL, NULL))
{ {
char *buf = (char *) ""; char *buf = (char *) "";
if (info.dli_sname != NULL) if (info->dli_sname != NULL)
{ {
size_t len = strlen (info.dli_sname); size_t len = strlen (info->dli_sname);
buf = alloca (len + 6 + 2 * sizeof (void *)); buf = alloca (len + 6 + 2 * sizeof (void *));
buf[0] = '('; buf[0] = '(';
__stpcpy (_fitoa (caller >= (const __ptr_t) info.dli_saddr __stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr
? caller - (const __ptr_t) info.dli_saddr ? caller - (const __ptr_t) info->dli_saddr
: (const __ptr_t) info.dli_saddr - caller, : (const __ptr_t) info->dli_saddr - caller,
__stpcpy (__mempcpy (buf + 1, info.dli_sname, __stpcpy (__mempcpy (buf + 1, info->dli_sname,
len), len),
caller >= (__ptr_t) info.dli_saddr caller >= (__ptr_t) info->dli_saddr
? "+0x" : "-0x"), ? "+0x" : "-0x"),
16, 0), 16, 0),
")"); ")");
} }
fprintf (mallstream, "@ %s%s%s[%p] ", fprintf (mallstream, "@ %s%s%s[%p] ",
info.dli_fname ?: "", info.dli_fname ? ":" : "", info->dli_fname ?: "", info->dli_fname ? ":" : "",
buf, caller); buf, caller);
} }
else else
#endif
fprintf (mallstream, "@ [%p] ", caller); fprintf (mallstream, "@ [%p] ", caller);
} }
} }
static Dl_info *
lock_and_info (const __ptr_t caller, Dl_info *mem)
{
if (caller == NULL)
return NULL;
Dl_info *res = _dl_addr (caller, mem, NULL, NULL) ? mem : NULL;
__libc_lock_lock (lock);
return res;
}
static void tr_freehook (__ptr_t, const __ptr_t) __THROW; static void tr_freehook (__ptr_t, const __ptr_t) __THROW;
static void static void
tr_freehook (ptr, caller) tr_freehook (ptr, caller)
@@ -127,8 +140,10 @@ tr_freehook (ptr, caller)
{ {
if (ptr == NULL) if (ptr == NULL)
return; return;
__libc_lock_lock (lock);
tr_where (caller); Dl_info mem;
Dl_info *info = lock_and_info (caller, &mem);
tr_where (caller, info);
/* Be sure to print it first. */ /* Be sure to print it first. */
fprintf (mallstream, "- %p\n", ptr); fprintf (mallstream, "- %p\n", ptr);
__libc_lock_unlock (lock); __libc_lock_unlock (lock);
@@ -152,7 +167,8 @@ tr_mallochook (size, caller)
{ {
__ptr_t hdr; __ptr_t hdr;
__libc_lock_lock (lock); Dl_info mem;
Dl_info *info = lock_and_info (caller, &mem);
__malloc_hook = tr_old_malloc_hook; __malloc_hook = tr_old_malloc_hook;
if (tr_old_malloc_hook != NULL) if (tr_old_malloc_hook != NULL)
@@ -161,7 +177,7 @@ tr_mallochook (size, caller)
hdr = (__ptr_t) malloc (size); hdr = (__ptr_t) malloc (size);
__malloc_hook = tr_mallochook; __malloc_hook = tr_mallochook;
tr_where (caller); tr_where (caller, info);
/* We could be printing a NULL here; that's OK. */ /* We could be printing a NULL here; that's OK. */
fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);
@@ -186,7 +202,8 @@ tr_reallochook (ptr, size, caller)
if (ptr == mallwatch) if (ptr == mallwatch)
tr_break (); tr_break ();
__libc_lock_lock (lock); Dl_info mem;
Dl_info *info = lock_and_info (caller, &mem);
__free_hook = tr_old_free_hook; __free_hook = tr_old_free_hook;
__malloc_hook = tr_old_malloc_hook; __malloc_hook = tr_old_malloc_hook;
@@ -199,7 +216,7 @@ tr_reallochook (ptr, size, caller)
__malloc_hook = tr_mallochook; __malloc_hook = tr_mallochook;
__realloc_hook = tr_reallochook; __realloc_hook = tr_reallochook;
tr_where (caller); tr_where (caller, info);
if (hdr == NULL) if (hdr == NULL)
/* Failed realloc. */ /* Failed realloc. */
fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size); fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size);
@@ -208,7 +225,7 @@ tr_reallochook (ptr, size, caller)
else else
{ {
fprintf (mallstream, "< %p\n", ptr); fprintf (mallstream, "< %p\n", ptr);
tr_where (caller); tr_where (caller, info);
fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size); fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size);
} }
@@ -229,7 +246,8 @@ tr_memalignhook (alignment, size, caller)
{ {
__ptr_t hdr; __ptr_t hdr;
__libc_lock_lock (lock); Dl_info mem;
Dl_info *info = lock_and_info (caller, &mem);
__memalign_hook = tr_old_memalign_hook; __memalign_hook = tr_old_memalign_hook;
__malloc_hook = tr_old_malloc_hook; __malloc_hook = tr_old_malloc_hook;
@@ -240,7 +258,7 @@ tr_memalignhook (alignment, size, caller)
__memalign_hook = tr_memalignhook; __memalign_hook = tr_memalignhook;
__malloc_hook = tr_mallochook; __malloc_hook = tr_mallochook;
tr_where (caller); tr_where (caller, info);
/* We could be printing a NULL here; that's OK. */ /* We could be printing a NULL here; that's OK. */
fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size);