diff options
author | Ulrich Drepper <drepper@gmail.com> | 2011-05-16 00:58:33 -0400 |
---|---|---|
committer | Ulrich Drepper <drepper@gmail.com> | 2011-05-16 00:58:33 -0400 |
commit | 56e5eb4619a936a3b63ae71f89038d69becd2999 (patch) | |
tree | e6005c7864f9b4ecd3f3bdfcae9b5bad9c294045 | |
parent | 6ce7537960cf42a0a6b0fc70957d5ce2ba9838de (diff) | |
download | glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.tar.gz glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.tar.xz glibc-56e5eb4619a936a3b63ae71f89038d69becd2999.zip |
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.
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | NEWS | 16 | ||||
-rw-r--r-- | malloc/mtrace.c | 64 |
3 files changed, 59 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog index cd89f3f7e4..4d3cf6d4ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,15 @@ 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 used and couldn't be at all thread-safe. diff --git a/NEWS b/NEWS index 7100e1dbcb..74e676fd84 100644 --- a/NEWS +++ b/NEWS @@ -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. See the end for copying conditions. @@ -9,13 +9,13 @@ Version 2.14 * The following bugs are resolved with this release: - 386, 7101, 9730, 9732, 9809, 10138, 10149, 10157, 11257, 11258, 11487, - 11532, 11578, 11653, 11668, 11724, 11901, 11945, 11947, 11952, 12052, - 12083, 12158, 12178, 12200, 12346, 12393, 12420, 12432, 12445, 12449, - 12453, 12454, 12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, - 12541, 12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611, 12625, - 12626, 12631, 12650, 12653, 12655, 12660, 12681, 12685, 12711, 12713, - 12714, 12717, 12723, 12724, 12734, 12738 + 386, 6420, 7101, 9730, 9732, 9809, 10138, 10149, 10157, 11257, 11258, + 11487, 11532, 11578, 11653, 11668, 11724, 11901, 11945, 11947, 11952, + 12052, 12083, 12158, 12178, 12200, 12346, 12393, 12420, 12432, 12445, + 12449, 12453, 12454, 12460, 12469, 12489, 12509, 12510, 12511, 12518, + 12527, 12541, 12545, 12551, 12582, 12583, 12587, 12597, 12601, 12611, + 12625, 12626, 12631, 12650, 12653, 12655, 12660, 12681, 12685, 12711, + 12713, 12714, 12717, 12723, 12724, 12734, 12738 * The RPC implementation in libc is obsoleted. Old programs keep working but new programs cannot be linked with the routines in libc anymore. diff --git a/malloc/mtrace.c b/malloc/mtrace.c index 51be396aaa..b55449f1ea 100644 --- a/malloc/mtrace.c +++ b/malloc/mtrace.c @@ -79,46 +79,59 @@ 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 internal_function -tr_where (caller) +tr_where (caller, info) const __ptr_t caller; + Dl_info *info; { if (caller != NULL) { -#ifdef HAVE_ELF - Dl_info info; - if (_dl_addr (caller, &info, NULL, NULL)) + if (info != NULL) { 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[0] = '('; - __stpcpy (_fitoa (caller >= (const __ptr_t) info.dli_saddr - ? caller - (const __ptr_t) info.dli_saddr - : (const __ptr_t) info.dli_saddr - caller, - __stpcpy (__mempcpy (buf + 1, info.dli_sname, + __stpcpy (_fitoa (caller >= (const __ptr_t) info->dli_saddr + ? caller - (const __ptr_t) info->dli_saddr + : (const __ptr_t) info->dli_saddr - caller, + __stpcpy (__mempcpy (buf + 1, info->dli_sname, len), - caller >= (__ptr_t) info.dli_saddr + caller >= (__ptr_t) info->dli_saddr ? "+0x" : "-0x"), 16, 0), ")"); } fprintf (mallstream, "@ %s%s%s[%p] ", - info.dli_fname ?: "", info.dli_fname ? ":" : "", + info->dli_fname ?: "", info->dli_fname ? ":" : "", buf, caller); } else -#endif 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, caller) @@ -127,8 +140,10 @@ tr_freehook (ptr, caller) { if (ptr == NULL) 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. */ fprintf (mallstream, "- %p\n", ptr); __libc_lock_unlock (lock); @@ -152,7 +167,8 @@ tr_mallochook (size, caller) { __ptr_t hdr; - __libc_lock_lock (lock); + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); __malloc_hook = tr_old_malloc_hook; if (tr_old_malloc_hook != NULL) @@ -161,7 +177,7 @@ tr_mallochook (size, caller) hdr = (__ptr_t) malloc (size); __malloc_hook = tr_mallochook; - tr_where (caller); + tr_where (caller, info); /* We could be printing a NULL here; that's OK. */ fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); @@ -186,7 +202,8 @@ tr_reallochook (ptr, size, caller) if (ptr == mallwatch) tr_break (); - __libc_lock_lock (lock); + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); __free_hook = tr_old_free_hook; __malloc_hook = tr_old_malloc_hook; @@ -199,7 +216,7 @@ tr_reallochook (ptr, size, caller) __malloc_hook = tr_mallochook; __realloc_hook = tr_reallochook; - tr_where (caller); + tr_where (caller, info); if (hdr == NULL) /* Failed realloc. */ fprintf (mallstream, "! %p %#lx\n", ptr, (unsigned long int) size); @@ -208,7 +225,7 @@ tr_reallochook (ptr, size, caller) else { fprintf (mallstream, "< %p\n", ptr); - tr_where (caller); + tr_where (caller, info); fprintf (mallstream, "> %p %#lx\n", hdr, (unsigned long int) size); } @@ -229,7 +246,8 @@ tr_memalignhook (alignment, size, caller) { __ptr_t hdr; - __libc_lock_lock (lock); + Dl_info mem; + Dl_info *info = lock_and_info (caller, &mem); __memalign_hook = tr_old_memalign_hook; __malloc_hook = tr_old_malloc_hook; @@ -240,7 +258,7 @@ tr_memalignhook (alignment, size, caller) __memalign_hook = tr_memalignhook; __malloc_hook = tr_mallochook; - tr_where (caller); + tr_where (caller, info); /* We could be printing a NULL here; that's OK. */ fprintf (mallstream, "+ %p %#lx\n", hdr, (unsigned long int) size); |