|
|
5f7b84 |
commit 11b451c8868d8a2b0edc5dfd44fc58d9ee538be0
|
|
|
5f7b84 |
Author: Mark Wielaard <mark@klomp.org>
|
|
|
5f7b84 |
Date: Wed May 15 17:14:01 2019 +0200
|
|
|
5f7b84 |
|
|
|
5f7b84 |
dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once) [BZ# 24476]
|
|
|
5f7b84 |
|
|
|
5f7b84 |
dlerror.c (__dlerror_main_freeres) will try to free resources which only
|
|
|
5f7b84 |
have been initialized when init () has been called. That function is
|
|
|
5f7b84 |
called when resources are needed using __libc_once (once, init) where
|
|
|
5f7b84 |
once is a __libc_once_define (static, once) in the dlerror.c file.
|
|
|
5f7b84 |
Trying to free those resources if init () hasn't been called will
|
|
|
5f7b84 |
produce errors under valgrind memcheck. So guard the freeing of those
|
|
|
5f7b84 |
resources using __libc_once_get (once) and make sure we have a valid
|
|
|
5f7b84 |
key. Also add a similar guard to __dlerror ().
|
|
|
5f7b84 |
|
|
|
5f7b84 |
* dlfcn/dlerror.c (__dlerror_main_freeres): Guard using
|
|
|
5f7b84 |
__libc_once_get (once) and static_bug == NULL.
|
|
|
5f7b84 |
(__dlerror): Check we have a valid key, set result to static_buf
|
|
|
5f7b84 |
otherwise.
|
|
|
5f7b84 |
|
|
|
5f7b84 |
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
|
|
5f7b84 |
|
|
|
5f7b84 |
diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
|
|
|
5f7b84 |
index 96bf92533335036b..06732460ea1512cd 100644
|
|
|
5f7b84 |
--- a/dlfcn/dlerror.c
|
|
|
5f7b84 |
+++ b/dlfcn/dlerror.c
|
|
|
5f7b84 |
@@ -72,9 +72,16 @@ __dlerror (void)
|
|
|
5f7b84 |
__libc_once (once, init);
|
|
|
5f7b84 |
|
|
|
5f7b84 |
/* Get error string. */
|
|
|
5f7b84 |
- result = (struct dl_action_result *) __libc_getspecific (key);
|
|
|
5f7b84 |
- if (result == NULL)
|
|
|
5f7b84 |
- result = &last_result;
|
|
|
5f7b84 |
+ if (static_buf != NULL)
|
|
|
5f7b84 |
+ result = static_buf;
|
|
|
5f7b84 |
+ else
|
|
|
5f7b84 |
+ {
|
|
|
5f7b84 |
+ /* init () has been run and we don't use the static buffer.
|
|
|
5f7b84 |
+ So we have a valid key. */
|
|
|
5f7b84 |
+ result = (struct dl_action_result *) __libc_getspecific (key);
|
|
|
5f7b84 |
+ if (result == NULL)
|
|
|
5f7b84 |
+ result = &last_result;
|
|
|
5f7b84 |
+ }
|
|
|
5f7b84 |
|
|
|
5f7b84 |
/* Test whether we already returned the string. */
|
|
|
5f7b84 |
if (result->returned != 0)
|
|
|
5f7b84 |
@@ -230,13 +237,19 @@ free_key_mem (void *mem)
|
|
|
5f7b84 |
void
|
|
|
5f7b84 |
__dlerror_main_freeres (void)
|
|
|
5f7b84 |
{
|
|
|
5f7b84 |
- void *mem;
|
|
|
5f7b84 |
/* Free the global memory if used. */
|
|
|
5f7b84 |
check_free (&last_result);
|
|
|
5f7b84 |
- /* Free the TSD memory if used. */
|
|
|
5f7b84 |
- mem = __libc_getspecific (key);
|
|
|
5f7b84 |
- if (mem != NULL)
|
|
|
5f7b84 |
- free_key_mem (mem);
|
|
|
5f7b84 |
+
|
|
|
5f7b84 |
+ if (__libc_once_get (once) && static_buf == NULL)
|
|
|
5f7b84 |
+ {
|
|
|
5f7b84 |
+ /* init () has been run and we don't use the static buffer.
|
|
|
5f7b84 |
+ So we have a valid key. */
|
|
|
5f7b84 |
+ void *mem;
|
|
|
5f7b84 |
+ /* Free the TSD memory if used. */
|
|
|
5f7b84 |
+ mem = __libc_getspecific (key);
|
|
|
5f7b84 |
+ if (mem != NULL)
|
|
|
5f7b84 |
+ free_key_mem (mem);
|
|
|
5f7b84 |
+ }
|
|
|
5f7b84 |
}
|
|
|
5f7b84 |
|
|
|
5f7b84 |
struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));
|