diff options
author | Carlos O'Donell <carlos@redhat.com> | 2018-06-22 09:28:47 -0400 |
---|---|---|
committer | Carlos O'Donell <carlos@redhat.com> | 2018-06-29 22:39:06 -0400 |
commit | 2827ab990aefbb0e53374199b875d98f116d6390 (patch) | |
tree | 0063b4c07be87d887d4a4893b9681b9e61479e8b /dlfcn | |
parent | 37d3d244e1a0ca7e7ac89b8e768e665adbb2e2d8 (diff) | |
download | glibc-2827ab990aefbb0e53374199b875d98f116d6390.zip glibc-2827ab990aefbb0e53374199b875d98f116d6390.tar.gz glibc-2827ab990aefbb0e53374199b875d98f116d6390.tar.bz2 |
libc: Extend __libc_freeres framework (Bug 23329).
The __libc_freeres framework does not extend to non-libc.so objects.
This causes problems in general for valgrind and mtrace detecting
unfreed objects in both libdl.so and libpthread.so. This change is
a pre-requisite to properly moving the malloc hooks out of malloc
since such a move now requires precise accounting of all allocated
data before destructors are run.
This commit adds a proper hook in libc.so.6 for both libdl.so and
for libpthread.so, this ensures that shm-directory.c which uses
freeit () to free memory is called properly. We also remove the
nptl_freeres hook and fall back to using weak-ref-and-check idiom
for a loaded libpthread.so, thus making this process similar for
all DSOs.
Lastly we follow best practice and use explicit free calls for
both libdl.so and libpthread.so instead of the generic hook process
which has undefined order.
Tested on x86_64 with no regressions.
Signed-off-by: DJ Delorie <dj@redhat.com>
Signed-off-by: Carlos O'Donell <carlos@redhat.com>
Diffstat (limited to 'dlfcn')
-rw-r--r-- | dlfcn/Makefile | 2 | ||||
-rw-r--r-- | dlfcn/Versions | 1 | ||||
-rw-r--r-- | dlfcn/dlerror.c | 14 | ||||
-rw-r--r-- | dlfcn/dlfreeres.c | 29 | ||||
-rw-r--r-- | dlfcn/sdlfreeres.c | 1 |
5 files changed, 46 insertions, 1 deletions
diff --git a/dlfcn/Makefile b/dlfcn/Makefile index 56dcae0..34f9923 100644 --- a/dlfcn/Makefile +++ b/dlfcn/Makefile @@ -22,7 +22,7 @@ include ../Makeconfig headers := bits/dlfcn.h dlfcn.h extra-libs := libdl libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \ - dlmopen dlfcn + dlmopen dlfcn dlfreeres routines := $(patsubst %,s%,$(filter-out dlfcn,$(libdl-routines))) elide-routines.os := $(routines) diff --git a/dlfcn/Versions b/dlfcn/Versions index 97902f0..1df6925 100644 --- a/dlfcn/Versions +++ b/dlfcn/Versions @@ -13,5 +13,6 @@ libdl { } GLIBC_PRIVATE { _dlfcn_hook; + __libdl_freeres; } } diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c index 04dce9d..33574fa 100644 --- a/dlfcn/dlerror.c +++ b/dlfcn/dlerror.c @@ -24,6 +24,7 @@ #include <string.h> #include <libc-lock.h> #include <ldsodefs.h> +#include <libc-symbols.h> #if !defined SHARED && IS_IN (libdl) @@ -222,6 +223,19 @@ free_key_mem (void *mem) # ifdef SHARED +/* Free the dlerror-related resources. */ +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); +} + struct dlfcn_hook *_dlfcn_hook __attribute__((nocommon)); libdl_hidden_data_def (_dlfcn_hook) diff --git a/dlfcn/dlfreeres.c b/dlfcn/dlfreeres.c new file mode 100644 index 0000000..4004db0 --- /dev/null +++ b/dlfcn/dlfreeres.c @@ -0,0 +1,29 @@ +/* Clean up allocated libdl memory on demand. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <set-hooks.h> +#include <libc-symbols.h> +#include <dlfcn.h> + +/* Free libdl.so resources. + Note: Caller ensures we are called only once. */ +void +__libdl_freeres (void) +{ + call_function_static_weak (__dlerror_main_freeres); +} diff --git a/dlfcn/sdlfreeres.c b/dlfcn/sdlfreeres.c new file mode 100644 index 0000000..7347672 --- /dev/null +++ b/dlfcn/sdlfreeres.c @@ -0,0 +1 @@ +#include "dlfreeres.c" |