malloc: Remove __malloc_initialize_hook from the API [BZ #19564]

__malloc_initialize_hook is interposed by application code, so
the usual approach to define a compatibility symbol does not work.
This commit adds a new mechanism based on #pragma GCC poison in
<stdc-predef.h>.
This commit is contained in:
Florian Weimer 2016-06-10 10:46:05 +02:00
parent f00faa4a43
commit 2ba3cfa160
10 changed files with 92 additions and 30 deletions

View File

@ -1,3 +1,23 @@
2016-06-10 Florian Weimer <fweimer@redhat.com>
[BZ #19564]
Remove __malloc_initialize_hook from the API.
* malloc/malloc.h (__malloc_initialize_hook): Remove.
* include/stdc-predef.h (__malloc_initialize_hook): Poison with
#pragma GCC poison.
* malloc/malloc-hooks.h: New file.
* malloc/arena.c (ptmalloc_init): Use old__malloc_initialize_hook.
* malloc/malloc.c (HAVE_MALLOC_INIT_HOOK): New.
(old__malloc_initialize_hook): Rename from
__malloc_initialize_hook to evade poisoning. Turn into compat
symbol.
* malloc/mcheck-init.c (old__malloc_initialize_hook): Rename from
__malloc_initialize_hook.
* malloc/Makefile (poisoned_apis, unpoisoned_api_defines): New.
(mallo.c, mcheck-init.c): Compile with unpoisoned symbol.
* manual/memory.texi (Hooks for Malloc): Remove
__malloc_initialize_hook. Adjust hook example.
2016-06-09 Joseph Myers <joseph@codesourcery.com> 2016-06-09 Joseph Myers <joseph@codesourcery.com>
[BZ #20235] [BZ #20235]

3
NEWS
View File

@ -33,6 +33,9 @@ Version 2.24
group: files [SUCCESS=merge] nis group: files [SUCCESS=merge] nis
Implemented by Stephen Gallagher (Red Hat). Implemented by Stephen Gallagher (Red Hat).
* The deprecated __malloc_initialize_hook variable has been removed from the
API.
Security related changes: Security related changes:
* An unnecessary stack copy in _nss_dns_getnetbyname_r was removed. It * An unnecessary stack copy in _nss_dns_getnetbyname_r was removed. It

View File

@ -57,4 +57,11 @@
/* We do not support C11 <threads.h>. */ /* We do not support C11 <threads.h>. */
#define __STDC_NO_THREADS__ 1 #define __STDC_NO_THREADS__ 1
/* Remove symbols from the API which can be interposed. */
#if defined (__GNUC__)
# if __GNUC__ >= 4
# pragma GCC poison __malloc_initialize_hook
# endif /* __GNUC__ >= 4 */
#endif /* __GNUC__ */
#endif #endif

View File

@ -115,6 +115,20 @@ endif
include ../Rules include ../Rules
# Support references to removed APIs. We use #pragma GCC poison in
# <stdc-predef.h> to make it difficult to reference them. For select
# source files, we work around this poisoning by defining a macro on
# the command line (which is processed before <stdc-predef.h> and can
# therefore use tokens poisoned later).
poisoned_apis = \
__malloc_initialize_hook \
unpoisoned_api_defines := \
$(foreach sym,$(poisoned_apis), \
$(patsubst %,-Dold%, $(sym))=$(sym))
CPPFLAGS-malloc.c = $(unpoisoned_api_defines)
CPPFLAGS-mcheck-init.c = $(unpoisoned_api_defines)
CFLAGS-mcheck-init.c = $(PIC-ccflag) CFLAGS-mcheck-init.c = $(PIC-ccflag)
CFLAGS-obstack.c = $(uses-callbacks) CFLAGS-obstack.c = $(uses-callbacks)

View File

@ -340,9 +340,11 @@ ptmalloc_init (void)
if (check_action != 0) if (check_action != 0)
__malloc_check_init (); __malloc_check_init ();
} }
void (*hook) (void) = atomic_forced_read (__malloc_initialize_hook); #if HAVE_MALLOC_INIT_HOOK
void (*hook) (void) = atomic_forced_read (old__malloc_initialize_hook);
if (hook != NULL) if (hook != NULL)
(*hook)(); (*hook)();
#endif
__malloc_initialized = 1; __malloc_initialized = 1;
} }

27
malloc/malloc-hooks.h Normal file
View File

@ -0,0 +1,27 @@
/* Internal declarations of malloc hooks no longer in the public API.
Copyright (C) 2016 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; see the file COPYING.LIB. If
not, see <http://www.gnu.org/licenses/>. */
#ifndef _MALLOC_HOOKS_H
#define _MALLOC_HOOKS_H
/* These hooks are no longer part of the public API and are poisoned
in <stdc-predef.h>. Their names here reflect the command-line
mapping which is used inside glibc to get past the poisoning. */
void (*old__malloc_initialize_hook) (void);
#endif /* _MALLOC_HOOKS_H */

View File

@ -491,6 +491,15 @@ void *(*__morecore)(ptrdiff_t) = __default_morecore;
#define HAVE_MREMAP 0 #define HAVE_MREMAP 0
#endif #endif
/* We may need to support __malloc_initialize_hook for backwards
compatibility. */
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_24)
# define HAVE_MALLOC_INIT_HOOK 1
#else
# define HAVE_MALLOC_INIT_HOOK 0
#endif
/* /*
This version of malloc supports the standard SVID/XPG mallinfo This version of malloc supports the standard SVID/XPG mallinfo
@ -1841,7 +1850,12 @@ static void *realloc_hook_ini (void *ptr, size_t sz,
static void *memalign_hook_ini (size_t alignment, size_t sz, static void *memalign_hook_ini (size_t alignment, size_t sz,
const void *caller) __THROW; const void *caller) __THROW;
void weak_variable (*__malloc_initialize_hook) (void) = NULL; #if HAVE_MALLOC_INIT_HOOK
void weak_variable (*old__malloc_initialize_hook) (void) = NULL;
compat_symbol (libc, old__malloc_initialize_hook,
old__malloc_initialize_hook, GLIBC_2_0);
#endif
void weak_variable (*__free_hook) (void *__ptr, void weak_variable (*__free_hook) (void *__ptr,
const void *) = NULL; const void *) = NULL;
void *weak_variable (*__malloc_hook) void *weak_variable (*__malloc_hook)

View File

@ -141,11 +141,6 @@ extern void *malloc_get_state (void) __THROW;
malloc_get_state(). */ malloc_get_state(). */
extern int malloc_set_state (void *__ptr) __THROW; extern int malloc_set_state (void *__ptr) __THROW;
/* Called once when malloc is initialized; redefining this variable in
the application provides the preferred way to set up the hook
pointers. */
extern void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) (void)
__MALLOC_DEPRECATED;
/* Hooks for debugging and user-defined versions. */ /* Hooks for debugging and user-defined versions. */
extern void (*__MALLOC_HOOK_VOLATILE __free_hook) (void *__ptr, extern void (*__MALLOC_HOOK_VOLATILE __free_hook) (void *__ptr,
const void *) const void *)

View File

@ -27,4 +27,4 @@ turn_on_mcheck (void)
mcheck (NULL); mcheck (NULL);
} }
void (*__malloc_initialize_hook) (void) = turn_on_mcheck; void (*old__malloc_initialize_hook) (void) = turn_on_mcheck;

View File

@ -1370,19 +1370,6 @@ should make sure to restore all the hooks to their previous value. When
coming back from the recursive call, all the hooks should be resaved coming back from the recursive call, all the hooks should be resaved
since a hook might modify itself. since a hook might modify itself.
@comment malloc.h
@comment GNU
@defvar __malloc_initialize_hook
The value of this variable is a pointer to a function that is called
once when the malloc implementation is initialized. This is a weak
variable, so it can be overridden in the application with a definition
like the following:
@smallexample
void (*@var{__malloc_initialize_hook}) (void) = my_init_hook;
@end smallexample
@end defvar
An issue to look out for is the time at which the malloc hook functions An issue to look out for is the time at which the malloc hook functions
can be safely installed. If the hook functions call the malloc-related can be safely installed. If the hook functions call the malloc-related
functions recursively, it is necessary that malloc has already properly functions recursively, it is necessary that malloc has already properly
@ -1393,11 +1380,6 @@ are assigned to @emph{before} the very first @code{malloc} call has
completed, because otherwise a chunk obtained from the ordinary, completed, because otherwise a chunk obtained from the ordinary,
un-hooked malloc may later be handed to @code{__free_hook}, for example. un-hooked malloc may later be handed to @code{__free_hook}, for example.
In both cases, the problem can be solved by setting up the hooks from
within a user-defined function pointed to by
@code{__malloc_initialize_hook}---then the hooks will be set up safely
at the right time.
Here is an example showing how to use @code{__malloc_hook} and Here is an example showing how to use @code{__malloc_hook} and
@code{__free_hook} properly. It installs a function that prints out @code{__free_hook} properly. It installs a function that prints out
information every time @code{malloc} or @code{free} is called. We just information every time @code{malloc} or @code{free} is called. We just
@ -1413,11 +1395,8 @@ static void my_init_hook (void);
static void *my_malloc_hook (size_t, const void *); static void *my_malloc_hook (size_t, const void *);
static void my_free_hook (void*, const void *); static void my_free_hook (void*, const void *);
/* Override initializing hook from the C library. */
void (*__malloc_initialize_hook) (void) = my_init_hook;
static void static void
my_init_hook (void) my_init (void)
@{ @{
old_malloc_hook = __malloc_hook; old_malloc_hook = __malloc_hook;
old_free_hook = __free_hook; old_free_hook = __free_hook;
@ -1465,6 +1444,7 @@ my_free_hook (void *ptr, const void *caller)
main () main ()
@{ @{
my_init ();
@dots{} @dots{}
@} @}
@end smallexample @end smallexample