diff --git a/ChangeLog b/ChangeLog index ce563e00ee..934fd6d341 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2019-05-15 Mark Wielaard + + [BZ#24476] + * dlfcn/dlerror.c (__dlerror_main_freeres): Guard using + __libc_once_get (once) and static_buf == NULL. + (__dlerror): Check we have a valid key, set result to static_buf + otherwise. + 2019-05-15 Andreas Schwab [BZ #20568] diff --git a/NEWS b/NEWS index 1da958d356..8bad7b0082 100644 --- a/NEWS +++ b/NEWS @@ -58,6 +58,7 @@ The following bugs are resolved with this release: [24097] Can't use 64-bit register for size_t in assembly codes for x32 (CVE-2019-6488) [24155] x32 memcmp can treat positive length as 0 (if sign bit in RDX is set) (CVE-2019-7309) [24161] __run_fork_handlers self-deadlocks in malloc/tst-mallocfork2 + [24476] dlfcn: Guard __dlerror_main_freeres with __libc_once_get (once) Security related changes: diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c index 96bf925333..06732460ea 100644 --- a/dlfcn/dlerror.c +++ b/dlfcn/dlerror.c @@ -72,9 +72,16 @@ __dlerror (void) __libc_once (once, init); /* Get error string. */ - result = (struct dl_action_result *) __libc_getspecific (key); - if (result == NULL) - result = &last_result; + if (static_buf != NULL) + result = static_buf; + else + { + /* init () has been run and we don't use the static buffer. + So we have a valid key. */ + result = (struct dl_action_result *) __libc_getspecific (key); + if (result == NULL) + result = &last_result; + } /* Test whether we already returned the string. */ if (result->returned != 0) @@ -230,13 +237,19 @@ free_key_mem (void *mem) void __dlerror_main_freeres (void) { - void *mem; /* Free the global memory if used. */ check_free (&last_result); - /* Free the TSD memory if used. */ - mem = __libc_getspecific (key); - if (mem != NULL) - free_key_mem (mem); + + if (__libc_once_get (once) && static_buf == NULL) + { + /* init () has been run and we don't use the static buffer. + So we have a valid key. */ + void *mem; + /* Free the TSD memory if used. */ + mem = __libc_getspecific (key); + if (mem != NULL) + free_key_mem (mem); + } } struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon));