This is the mail archive of the
glibc-cvs@sourceware.org
mailing list for the glibc project.
GNU C Library master sources branch zack/explicit-bzero created. glibc-2.24-447-g1e39d45
- From: zack at sourceware dot org
- To: glibc-cvs at sourceware dot org
- Date: 3 Dec 2016 16:45:30 -0000
- Subject: GNU C Library master sources branch zack/explicit-bzero created. glibc-2.24-447-g1e39d45
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".
The branch, zack/explicit-bzero has been created
at 1e39d45dc4259b32c5a00eee6ebe0a2caaae5245 (commit)
- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1e39d45dc4259b32c5a00eee6ebe0a2caaae5245
commit 1e39d45dc4259b32c5a00eee6ebe0a2caaae5245
Author: Zack Weinberg <zackw@panix.com>
Date: Sat Aug 8 21:23:46 2015 -0400
Use explicit_bzero where appropriate
I *believe* these are the only places where memset was being used
to clear buffers containing sensitive data. The compiler probably
couldn't optimize *all* of them out but it seems best to change them all.
The legacy DES implementation wasn't bothering to clear its buffers,
so I added that, mostly for consistency's sake.
* crypt/crypt-entry.c (__crypt_r): Clear key-dependent intermediate
data before returning, using explicit_bzero.
* crypt/md5-crypt.c (__md5_crypt_r): Likewise.
* crypt/sha256-crypt.c (__sha256_crypt_r): Likewise.
* crypt/sha512-crypt.c (__sha512_crypt_r): Likewise.
diff --git a/crypt/crypt-entry.c b/crypt/crypt-entry.c
index a7dfcca..2d72691 100644
--- a/crypt/crypt-entry.c
+++ b/crypt/crypt-entry.c
@@ -141,6 +141,17 @@ __crypt_r (const char *key, const char *salt,
* And convert back to 6 bit ASCII
*/
_ufc_output_conversion_r (res[0], res[1], salt, data);
+
+#ifdef _LIBC
+ /*
+ * Erase key-dependent intermediate data. Data dependent only on
+ * the salt is not considered sensitive.
+ */
+ __explicit_bzero (ktab, sizeof (ktab));
+ __explicit_bzero (data->keysched, sizeof (data->keysched));
+ __explicit_bzero (res, sizeof (res));
+#endif
+
return data->crypt_3_buf;
}
weak_alias (__crypt_r, crypt_r)
diff --git a/crypt/md5-crypt.c b/crypt/md5-crypt.c
index 2243bc7..617ccd3 100644
--- a/crypt/md5-crypt.c
+++ b/crypt/md5-crypt.c
@@ -288,13 +288,13 @@ __md5_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
#ifndef USE_NSS
__md5_init_ctx (&ctx);
__md5_finish_ctx (&ctx, alt_result);
- memset (&ctx, '\0', sizeof (ctx));
- memset (&alt_ctx, '\0', sizeof (alt_ctx));
+ __explicit_bzero (&ctx, sizeof (ctx));
+ __explicit_bzero (&alt_ctx, sizeof (alt_ctx));
#endif
if (copied_key != NULL)
- memset (copied_key, '\0', key_len);
+ __explicit_bzero (copied_key, key_len);
if (copied_salt != NULL)
- memset (copied_salt, '\0', salt_len);
+ __explicit_bzero (copied_salt, salt_len);
free (free_key);
return buffer;
diff --git a/crypt/sha256-crypt.c b/crypt/sha256-crypt.c
index d768234..53f00c0 100644
--- a/crypt/sha256-crypt.c
+++ b/crypt/sha256-crypt.c
@@ -371,16 +371,16 @@ __sha256_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
#ifndef USE_NSS
__sha256_init_ctx (&ctx);
__sha256_finish_ctx (&ctx, alt_result);
- memset (&ctx, '\0', sizeof (ctx));
- memset (&alt_ctx, '\0', sizeof (alt_ctx));
+ __explicit_bzero (&ctx, sizeof (ctx));
+ __explicit_bzero (&alt_ctx, sizeof (alt_ctx));
#endif
- memset (temp_result, '\0', sizeof (temp_result));
- memset (p_bytes, '\0', key_len);
- memset (s_bytes, '\0', salt_len);
+ __explicit_bzero (temp_result, sizeof (temp_result));
+ __explicit_bzero (p_bytes, key_len);
+ __explicit_bzero (s_bytes, salt_len);
if (copied_key != NULL)
- memset (copied_key, '\0', key_len);
+ __explicit_bzero (copied_key, key_len);
if (copied_salt != NULL)
- memset (copied_salt, '\0', salt_len);
+ __explicit_bzero (copied_salt, salt_len);
free (free_key);
free (free_pbytes);
diff --git a/crypt/sha512-crypt.c b/crypt/sha512-crypt.c
index f404c88..86b6354 100644
--- a/crypt/sha512-crypt.c
+++ b/crypt/sha512-crypt.c
@@ -393,16 +393,16 @@ __sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
#ifndef USE_NSS
__sha512_init_ctx (&ctx);
__sha512_finish_ctx (&ctx, alt_result);
- memset (&ctx, '\0', sizeof (ctx));
- memset (&alt_ctx, '\0', sizeof (alt_ctx));
+ __explicit_bzero (&ctx, sizeof (ctx));
+ __explicit_bzero (&alt_ctx, sizeof (alt_ctx));
#endif
- memset (temp_result, '\0', sizeof (temp_result));
- memset (p_bytes, '\0', key_len);
- memset (s_bytes, '\0', salt_len);
+ __explicit_bzero (temp_result, sizeof (temp_result));
+ __explicit_bzero (p_bytes, key_len);
+ __explicit_bzero (s_bytes, salt_len);
if (copied_key != NULL)
- memset (copied_key, '\0', key_len);
+ __explicit_bzero (copied_key, key_len);
if (copied_salt != NULL)
- memset (copied_salt, '\0', salt_len);
+ __explicit_bzero (copied_salt, salt_len);
free (free_key);
free (free_pbytes);
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=00436c52e30e4d36250cdfef4ffb15fae7290792
commit 00436c52e30e4d36250cdfef4ffb15fae7290792
Author: Zack Weinberg <zackw@panix.com>
Date: Mon Nov 14 12:28:26 2016 -0500
Add fortification and inline optimization of explicit_bzero.
By exposing __glibc_read_memory to external callers, we can write a
fortify wrapper for explicit_bzero in terms of __memset_chk and
__glibc_read_memory. There is no out-of-line __bzero_chk defined in
libc.so, so I see no need to add an out-of-line __explicit_bzero_chk
either.
We can also add a bits/string2.h macro that optimizes explicit_bzero
to memset + __glibc_read_memory, thus allowing the compiler to use
intrinsic code generation for memset. I think this is worth doing
because it partially addresses the problem pointed out in the manual,
where explicit_bzero might _cause_ sensitive data to be copied out of
registers onto the stack. With memset visible to the compiler, it
will just clear a scratch area on the stack and then call
__glibc_read_memory; it won't copy the sensitive data onto the stack
first. (But it still doesn't erase the sensitive data _in_ the
registers, so the warning in the manual is still appropriate.)
* string/bits/string2.h: Optimize explicit_bzero.
* string/bits/string3.h: Fortify explicit_bzero.
* debug/tst-chk1.c: Test fortification of explicit_bzero.
diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c
index 478c2fb..e87a279 100644
--- a/debug/tst-chk1.c
+++ b/debug/tst-chk1.c
@@ -160,6 +160,10 @@ do_test (void)
if (memcmp (buf, "aabcdabc\0\0", 10))
FAIL ();
+ explicit_bzero (buf + 6, 4);
+ if (memcmp (buf, "aabcda\0\0\0\0", 10))
+ FAIL ();
+
strcpy (buf + 4, "EDCBA");
if (memcmp (buf, "aabcEDCBA", 10))
FAIL ();
@@ -201,6 +205,10 @@ do_test (void)
if (memcmp (buf, "aabcdabc\0\0", 10))
FAIL ();
+ explicit_bzero (buf + 6, l0 + 4);
+ if (memcmp (buf, "aabcda\0\0\0\0", 10))
+ FAIL ();
+
strcpy (buf + 4, str1 + 5);
if (memcmp (buf, "aabcEDCBA", 10))
FAIL ();
@@ -256,6 +264,10 @@ do_test (void)
if (memcmp (a.buf1, "aabcdabc\0\0", 10))
FAIL ();
+ explicit_bzero (a.buf1 + 6, l0 + 4);
+ if (memcmp (a.buf1, "aabcda\0\0\0\0", 10))
+ FAIL ();
+
#if __USE_FORTIFY_LEVEL < 2
/* The following tests are supposed to crash with -D_FORTIFY_SOURCE=2
and sufficient GCC support, as the string operations overflow
@@ -346,6 +358,14 @@ do_test (void)
CHK_FAIL_END
CHK_FAIL_START
+ explicit_bzero (buf + 9, 2);
+ CHK_FAIL_END
+
+ CHK_FAIL_START
+ explicit_bzero (buf + 9, l0 + 2);
+ CHK_FAIL_END
+
+ CHK_FAIL_START
strcpy (buf + 5, str1 + 5);
CHK_FAIL_END
@@ -454,6 +474,14 @@ do_test (void)
bzero (a.buf1 + 9, l0 + 2);
CHK_FAIL_END
+ CHK_FAIL_START
+ explicit_bzero (a.buf1 + 9, 2);
+ CHK_FAIL_END
+
+ CHK_FAIL_START
+ explicit_bzero (a.buf1 + 9, l0 + 2);
+ CHK_FAIL_END
+
# if __USE_FORTIFY_LEVEL >= 2
# define O 0
# else
diff --git a/string/bits/string2.h b/string/bits/string2.h
index ca1eda9..d509533 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -57,6 +57,17 @@
# define __bzero(s, n) __builtin_memset (s, '\0', n)
#endif
+#if defined __USE_MISC
+/* As bzero, but the compiler will not delete a call to this function,
+ even if S is dead after the call. This is a macro instead of an
+ inline function _solely_ so that it will not get turned into an
+ external definition in string-inlines.o; it has its own .c file in
+ libc already. */
+# define explicit_bzero(s, n) \
+ (__extension__ ({ void *__s = (s); size_t __n = (n); \
+ memset (__s, '\0', __n); \
+ __glibc_read_memory (__s, __n); }))
+#endif
#ifndef _HAVE_STRING_ARCH_strchr
extern void *__rawmemchr (const void *__s, int __c);
diff --git a/string/bits/string3.h b/string/bits/string3.h
index 8f13b65..c9e2e62 100644
--- a/string/bits/string3.h
+++ b/string/bits/string3.h
@@ -42,6 +42,7 @@ __warndecl (__warn_memset_zero_len,
# ifdef __USE_MISC
# undef bcopy
# undef bzero
+# undef explicit_bzero
# endif
#endif
@@ -102,6 +103,13 @@ __NTH (bzero (void *__dest, size_t __len))
{
(void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
}
+
+__fortify_function void
+__NTH (explicit_bzero (void *__dest, size_t __len))
+{
+ (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
+ __glibc_read_memory (__dest, __len);
+}
#endif
__fortify_function char *
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=1836aadcedab8a28a3d4b4c0e276a719cb0c860c
commit 1836aadcedab8a28a3d4b4c0e276a719cb0c860c
Author: Zack Weinberg <zackw@panix.com>
Date: Thu Sep 15 07:29:44 2016 -0400
New string function explicit_bzero (from OpenBSD).
explicit_bzero(s, n) is the same as memset(s, 0, n), except that the
compiler is not allowed to delete a call to explicit_bzero even if the
memory pointed to by 's' is dead after the call. We achieve this effect
by defining it to call memset() and then a second function,
extern void __glibc_read_memory (const void *, size_t)
__attribute_noinline__;
which does nothing -- but the compiler is prevented from knowing that
it does nothing, and so the pointer "escapes" and the memory is not
treated as dead. (Concretely, __glibc_read_memory is forced
out-of-line, defined in a file containing nothing else, and comments
in both string/read_memory.c and string/Makefile document that it must
not be subject to link-time optimization.)
There are two new tests: test-explicit_bzero.c verifies the
visible semantics in the same way as the existing test-bzero.c,
and tst-xbzero-opt.c verifies the not-being-optimized-out property.
The latter is conceptually based on a test written by Matthew Dempsky
for the OpenBSD regression suite.
* string/explicit_bzero.c, string/read_memory.c: New routines.
* string/test-explicit_bzero.c, string/tst-xbzero-opt.c: New tests.
* string/Makefile (routines, strop-tests, tests): Add them.
* string/test-memset.c: Add ifdeffage for testing explicit_bzero.
* string/string.h [__USE_MISC]: Declare explicit_bzero and
__glibc_read_memory.
* include/string.h: Declare __internal_glibc_read_memory,
__explicit_bzero, and __internal_explicit_bzero.
* manual/string.texi: Document explicit_bzero.
* string/Versions [GLIBC_2.25]: Add explicit_bzero,
__explicit_bzero, and __glibc_read_memory.
* sysdeps/arm/nacl/libc.abilist
* sysdeps/unix/sysv/linux/aarch64/libc.abilist
* sysdeps/unix/sysv/linux/alpha/libc.abilist
* sysdeps/unix/sysv/linux/arm/libc.abilist
* sysdeps/unix/sysv/linux/hppa/libc.abilist
* sysdeps/unix/sysv/linux/i386/libc.abilist
* sysdeps/unix/sysv/linux/ia64/libc.abilist
* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
* sysdeps/unix/sysv/linux/microblaze/libc.abilist
* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
* sysdeps/unix/sysv/linux/nios2/libc.abilist
* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
* sysdeps/unix/sysv/linux/sh/libc.abilist
* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist:
Add entries for explicit_bzero, __explicit_bzero,
and __glibc_read_memory.
diff --git a/include/string.h b/include/string.h
index e145bfd..4185521 100644
--- a/include/string.h
+++ b/include/string.h
@@ -100,6 +100,18 @@ extern __typeof (memmem) __memmem;
libc_hidden_proto (__memmem)
libc_hidden_proto (__ffs)
+/* explicit_bzero is used in libcrypt. */
+extern __typeof (explicit_bzero) __explicit_bzero;
+extern __typeof (explicit_bzero) __internal_explicit_bzero;
+libc_hidden_proto (__internal_explicit_bzero)
+extern __typeof (__glibc_read_memory) __internal_glibc_read_memory;
+libc_hidden_proto (__internal_glibc_read_memory)
+/* Honor string[23].h overrides when present. */
+#ifdef explicit_bzero
+# define __explicit_bzero(s,n) explicit_bzero (s,n)
+# define __internal_explicit_bzero(s,n) explicit_bzero (s,n)
+#endif
+
libc_hidden_builtin_proto (memchr)
libc_hidden_builtin_proto (memcpy)
libc_hidden_builtin_proto (mempcpy)
diff --git a/manual/string.texi b/manual/string.texi
index 1986357..faa75ba 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -34,6 +34,8 @@ too.
* Search Functions:: Searching for a specific element or substring.
* Finding Tokens in a String:: Splitting a string into tokens by looking
for delimiters.
+* Erasing Sensitive Data:: Clearing memory which contains sensitive
+ data, after it's no longer needed.
* strfry:: Function for flash-cooking a string.
* Trivial Encryption:: Obscuring data.
* Encode Binary Data:: Encoding and Decoding of Binary Data.
@@ -2404,6 +2406,105 @@ contains no '/' bytes, then "." is returned. The prototype for this
function can be found in @file{libgen.h}.
@end deftypefun
+@node Erasing Sensitive Data
+@section Erasing Sensitive Data
+
+Sensitive data, such as cryptographic keys, should be erased from
+memory after use, to reduce the risk that a bug will expose it to the
+outside world. However, compiler optimizations may determine that an
+erasure operation is ``unnecessary,'' and remove it from the generated
+code, because no @emph{correct} program could access the variable or
+heap object containing the sensitive data after it's deallocated.
+Since erasure is a precaution against bugs, this optimization is
+inappropriate.
+
+The function @code{explicit_bzero} erases a block of memory, and
+guarantees that the compiler will not remove the erasure as
+``unnecessary.''
+
+@smallexample
+@group
+#include <string.h>
+
+extern void encrypt (const char *key, const char *in,
+ char *out, size_t n);
+extern void genkey (const char *phrase, char *key);
+
+void encrypt_with_phrase (const char *phrase, const char *in,
+ char *out, size_t n)
+@{
+ char key[16];
+ genkey (phrase, key);
+ encrypt (key, in, out, n);
+ explicit_bzero (key, 16);
+@}
+@end group
+@end smallexample
+
+@noindent
+In this example, if @code{memset}, @code{bzero}, or a hand-written
+loop had been used, the compiler might remove them as ``unnecessary.''
+
+@strong{Warning:} @code{explicit_bzero} does not guarantee that
+sensitive data is @emph{completely} erased from the computer's memory.
+There may be copies in temporary storage areas, such as registers and
+``scratch'' stack space; since these are invisible to the source code,
+a library function cannot erase them.
+
+Also, @code{explicit_bzero} only operates on RAM. If a sensitive data
+object never needs to have its address taken other than to call
+@code{explicit_bzero}, it might be stored entirely in CPU registers
+@emph{until} the call to @code{explicit_bzero}. Then it will be
+copied into RAM, the copy will be erased, and the original will remain
+intact. Data in RAM is more likely to be exposed by a bug than data
+in registers, so this creates a brief window where the data is at
+greater risk of exposure than it would have been if the program didn't
+try to erase it at all. @Theglibc{}'s implementation of
+@code{explicit_bzero} contains a hack that can prevent the data from
+being copied to RAM in this situation, but it may not always work.
+
+Declaring sensitive variables as @code{volatile} will make both the
+above problems @emph{worse}; a @code{volatile} variable will be stored
+in memory for its entire lifetime, and the compiler will make
+@emph{more} copies of it than it would otherwise have. Attempting to
+erase a normal variable ``by hand'' through a
+@code{volatile}-qualified pointer doesn't work at all---because the
+variable itself is not @code{volatile}, some compilers will ignore the
+qualification on the pointer and remove the erasure anyway.
+
+Having said all that, in most situations, using @code{explicit_bzero}
+is better than not using it. At present, the only way to do a more
+thorough job is to write the entire sensitive operation in assembly
+language. We anticipate that future compilers will recognize calls to
+@code{explicit_bzero} and take appropriate steps to erase all the
+copies of the affected data, whereever they may be.
+
+@comment string.h
+@comment BSD
+@deftypefun void explicit_bzero (void *@var{block}, size_t @var{len})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+
+@code{explicit_bzero} writes zero into @var{len} bytes of memory
+beginning at @var{block}, just as @code{bzero} would. The zeroes are
+always written, even if the compiler could determine that this is
+``unnecessary'' because no correct program could read them back.
+
+@strong{Note:} The @emph{only} optimization that @code{explicit_bzero}
+disables is removal of ``unnecessary'' writes to memory. The compiler
+can perform all the other optimizations that it could for a call to
+@code{memset}. For instance, it may replace the function call with
+inline memory writes, and it may assume that @var{block} cannot be a
+null pointer.
+
+@strong{Portability Note:} This function first appeared in OpenBSD 5.5
+and has not been standardized. Other systems may provide the same
+functionality under a different name, such as @code{explicit_memset},
+@code{memset_s}, or @code{SecureZeroMemory}.
+
+@Theglibc{} declares this function in @file{string.h}, but on other
+systems it may be in @file{strings.h} instead.
+@end deftypefun
+
@node strfry
@section strfry
diff --git a/string/Makefile b/string/Makefile
index 69d3f80..0b6486e 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -41,20 +41,26 @@ routines := strcat strchr strcmp strcoll strcpy strcspn \
addsep replace) \
envz basename \
strcoll_l strxfrm_l string-inlines memrchr \
- xpg-strerror strerror_l
+ xpg-strerror strerror_l explicit_bzero
+
+# Attention future hackers trying to enable link-time optimization for
+# glibc: this file *must not* be subject to LTO. It is added separately
+# to 'routines' to document this. See comments in this file for details.
+routines += read_memory
strop-tests := memchr memcmp memcpy memmove mempcpy memset memccpy \
stpcpy stpncpy strcat strchr strcmp strcpy strcspn \
strlen strncmp strncpy strpbrk strrchr strspn memmem \
strstr strcasestr strnlen strcasecmp strncasecmp \
- strncat rawmemchr strchrnul bcopy bzero memrchr
+ strncat rawmemchr strchrnul bcopy bzero memrchr \
+ explicit_bzero
tests := tester inl-tester noinl-tester testcopy test-ffs \
tst-strlen stratcliff tst-svc tst-inlcall \
bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap \
tst-strtok tst-strxfrm bug-strcoll1 tst-strfry \
bug-strtok1 $(addprefix test-,$(strop-tests)) \
bug-envz1 tst-strxfrm2 tst-endian tst-svc2 \
- tst-strtok_r bug-strcoll2 tst-cmp
+ tst-strtok_r bug-strcoll2 tst-cmp tst-xbzero-opt
xtests = tst-strcoll-overflow
diff --git a/string/Versions b/string/Versions
index 475c1fd..4f434f3 100644
--- a/string/Versions
+++ b/string/Versions
@@ -82,4 +82,14 @@ libc {
}
GLIBC_2.24 {
}
+ GLIBC_2.25 {
+ # used by inlines in bits/string2.h and bits/string3.h
+ __glibc_read_memory;
+
+ # used by libcrypt
+ __explicit_bzero;
+
+ # e*
+ explicit_bzero;
+ }
}
diff --git a/string/explicit_bzero.c b/string/explicit_bzero.c
new file mode 100644
index 0000000..6c3dc9a
--- /dev/null
+++ b/string/explicit_bzero.c
@@ -0,0 +1,33 @@
+/* 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; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <features.h>
+#undef __USE_STRING_INLINES
+#define __NO_STRING_INLINES
+#include <string.h>
+
+/* Set LEN bytes of S to 0. The compiler will not delete a call to
+ this function, even if S is dead after the call. */
+void
+__internal_explicit_bzero (void *s, size_t len)
+{
+ memset (s, '\0', len);
+ __internal_glibc_read_memory (s, len);
+}
+libc_hidden_def (__internal_explicit_bzero)
+strong_alias (__internal_explicit_bzero, __explicit_bzero)
+weak_alias (__internal_explicit_bzero, explicit_bzero)
diff --git a/string/read_memory.c b/string/read_memory.c
new file mode 100644
index 0000000..c4a5990
--- /dev/null
+++ b/string/read_memory.c
@@ -0,0 +1,41 @@
+/* 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; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <string.h>
+
+/* This function is an optimization fence. It doesn't do anything
+ itself, but calls to it prevent calls to explicit_bzero from being
+ optimized away. In order to achieve this effect, this function
+ must never, under any circumstances, be inlined or subjected to
+ inter-procedural optimization. string.h declares this function
+ with attributes that, in conjunction with the no-op asm insert, are
+ sufficient to prevent problems in the current (2016) generation of
+ compilers, but *only if* this file is *not* compiled with -flto.
+ At present, this is not an issue since glibc is never compiled with
+ -flto, but should that ever change, this file must be excepted.
+
+ The 'volatile' below is technically not necessary but is included
+ for explicitness. */
+
+void
+internal_function
+__internal_glibc_read_memory(const void *s, size_t len)
+{
+ asm volatile ("");
+}
+libc_hidden_def (__internal_glibc_read_memory)
+strong_alias (__internal_glibc_read_memory, __glibc_read_memory)
diff --git a/string/string.h b/string/string.h
index b103e64..3036679 100644
--- a/string/string.h
+++ b/string/string.h
@@ -453,6 +453,15 @@ extern void bcopy (const void *__src, void *__dest, size_t __n)
/* Set N bytes of S to 0. */
extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));
+/* As bzero, but the compiler will not delete a call to this
+ function, even if S is dead after the call. */
+extern void explicit_bzero (void *__s, size_t __n) __THROW __nonnull ((1));
+
+/* Optimization fence, used by bits/string2.h and bits/string3.h
+ inline versions of explicit_bzero. */
+extern void __glibc_read_memory (const void *__s, size_t __n)
+ __THROW __nonnull ((1)) __attribute_noinline__;
+
/* Compare N bytes of S1 and S2 (same as memcmp). */
extern int bcmp (const void *__s1, const void *__s2, size_t __n)
__THROW __attribute_pure__ __nonnull ((1, 2));
diff --git a/string/test-explicit_bzero.c b/string/test-explicit_bzero.c
new file mode 100644
index 0000000..5a4543b
--- /dev/null
+++ b/string/test-explicit_bzero.c
@@ -0,0 +1,20 @@
+/* Test and measure explicit_bzero.
+ 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; if not, see
+ <http://www.gnu.org/licenses/>. */
+#define TEST_EXPLICIT_BZERO
+#define TEST_BZERO
+#include "test-memset.c"
diff --git a/string/test-memset.c b/string/test-memset.c
index fee3bdf..7ca4f20 100644
--- a/string/test-memset.c
+++ b/string/test-memset.c
@@ -19,7 +19,11 @@
#define TEST_MAIN
#ifdef TEST_BZERO
-# define TEST_NAME "bzero"
+# ifdef TEST_EXPLICIT_BZERO
+# define TEST_NAME "explicit_bzero"
+# else
+# define TEST_NAME "bzero"
+# endif
#else
# ifndef WIDE
# define TEST_NAME "memset"
@@ -56,7 +60,11 @@ void builtin_bzero (char *, size_t);
IMPL (simple_bzero, 0)
IMPL (builtin_bzero, 0)
+#ifdef TEST_EXPLICIT_BZERO
+IMPL (explicit_bzero, 1)
+#else
IMPL (bzero, 1)
+#endif
void
simple_bzero (char *s, size_t n)
diff --git a/string/tst-xbzero-opt.c b/string/tst-xbzero-opt.c
new file mode 100644
index 0000000..7d697f4
--- /dev/null
+++ b/string/tst-xbzero-opt.c
@@ -0,0 +1,289 @@
+/* Test that explicit_bzero block clears are not optimized out.
+ 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; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This test is conceptually based on a test designed by Matthew
+ Dempsky for the OpenBSD regression suite:
+ <openbsd>/src/regress/lib/libc/explicit_bzero/explicit_bzero.c.
+ The basic idea is, we have a function that contains a
+ block-clearing operation (not necessarily explicit_bzero), after
+ which the block is dead, in the compiler-jargon sense. Execute
+ that function while running on a user-allocated alternative
+ stack. Then we have another pointer to the memory region affected
+ by the block clear -- namely, the original allocation for the
+ alternative stack -- and can find out whether it actually happened.
+
+ The OpenBSD test uses sigaltstack and SIGUSR1 to get onto an
+ alternative stack. This causes a number of awkward problems; some
+ operating systems (e.g. Solaris and OSX) wipe the signal stack upon
+ returning to the normal stack, there's no way to be sure that other
+ processes running on the same system will not interfere, and the
+ signal stack is very small so it's not safe to call printf there.
+ This implementation instead uses the <ucontext.h> coroutine
+ interface. The coroutine stack is still too small to safely use
+ printf, but we know the OS won't erase it, so we can do all the
+ checks and printing from the normal stack. */
+
+#define _GNU_SOURCE 1
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+/* A byte pattern that is unlikely to occur by chance: the first 16
+ prime numbers (OEIS A000040). */
+static const unsigned char test_pattern[16] =
+{
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53
+};
+
+/* Immediately after each subtest returns, we call swapcontext to get
+ back onto the main stack. That call might itself overwrite the
+ test pattern, so we fill a modest-sized buffer with copies of it
+ and check whether any of them survived. */
+
+#define PATTERN_SIZE (sizeof test_pattern)
+#define PATTERN_REPS 32
+#define TEST_BUFFER_SIZE (PATTERN_SIZE * PATTERN_REPS)
+
+/* There are three subtests, two of which are sanity checks.
+ Each test follows this sequence:
+
+ main coroutine
+ ---- --------
+ advance cur_subtest
+ swap
+ call setup function
+ prepare test buffer
+ swap
+ verify that buffer
+ was filled in
+ swap
+ possibly clear buffer
+ return
+ swap
+ check buffer again,
+ according to test
+ expectation
+
+ In the "no_clear" case, we don't do anything to the test buffer
+ between preparing it and letting it go out of scope, and we expect
+ to find it. This confirms that the test buffer does get filled in
+ and we can find it from the stack buffer. In the "ordinary_clear"
+ case, we clear it using memset, and we expect to find it. This
+ confirms that the compiler can optimize out block clears in this
+ context; if it can't, the real test might be succeeding for the
+ wrong reason. Finally, the "explicit_clear" case uses
+ explicit_bzero and expects _not_ to find the test buffer, which is
+ the real test. */
+
+static ucontext_t uc_main, uc_co;
+
+/* Always check the test buffer immediately after filling it; this
+ makes externally visible side effects depend on the buffer existing
+ and having been filled in. */
+static void
+prepare_test_buffer (unsigned char *buf)
+{
+ for (unsigned int i = 0; i < PATTERN_REPS; i++)
+ memcpy (buf + i*PATTERN_SIZE, test_pattern, PATTERN_SIZE);
+
+ if (swapcontext (&uc_co, &uc_main))
+ abort ();
+}
+
+static void
+setup_no_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf);
+}
+
+static void
+setup_ordinary_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf);
+ memset (buf, 0, TEST_BUFFER_SIZE);
+}
+
+static void
+setup_explicit_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf);
+ explicit_bzero (buf, TEST_BUFFER_SIZE);
+}
+
+enum test_expectation { EXPECT_NONE, EXPECT_SOME, EXPECT_ALL };
+struct subtest
+{
+ void (*setup_subtest) (void);
+ const char *label;
+ enum test_expectation expected;
+};
+static const struct subtest *cur_subtest;
+
+static const struct subtest subtests[] =
+{
+ { setup_no_clear, "no clear", EXPECT_SOME },
+ { setup_ordinary_clear, "ordinary clear", EXPECT_SOME },
+ { setup_explicit_clear, "explicit clear", EXPECT_NONE },
+ { 0, 0, -1 }
+};
+
+static void
+test_coroutine (void)
+{
+ while (cur_subtest->setup_subtest)
+ {
+ cur_subtest->setup_subtest ();
+ if (swapcontext (&uc_co, &uc_main))
+ abort ();
+ }
+}
+
+/* All the code above this point runs on the coroutine stack.
+ All the code below this point runs on the main stack. */
+
+static int test_status;
+static unsigned char *co_stack_buffer;
+static size_t co_stack_size;
+
+static unsigned int
+count_test_patterns (unsigned char *buf, size_t bufsiz)
+{
+ unsigned char *first = memmem (buf, bufsiz, test_pattern, PATTERN_SIZE);
+ if (!first)
+ return 0;
+ unsigned int cnt = 0;
+ for (unsigned int i = 0; i < PATTERN_REPS; i++)
+ {
+ unsigned char *p = first + i*PATTERN_SIZE;
+ if (p + PATTERN_SIZE - buf > bufsiz)
+ break;
+ if (memcmp (p, test_pattern, PATTERN_SIZE) == 0)
+ cnt++;
+ }
+ return cnt;
+}
+
+static void
+check_test_buffer (enum test_expectation expected,
+ const char *label, const char *stage)
+{
+ unsigned int cnt = count_test_patterns (co_stack_buffer, co_stack_size);
+ switch (expected)
+ {
+ case EXPECT_NONE:
+ if (cnt == 0)
+ printf ("PASS: %s/%s: expected 0 got %d\n", label, stage, cnt);
+ else
+ {
+ printf ("FAIL: %s/%s: expected 0 got %d\n", label, stage, cnt);
+ test_status = 1;
+ }
+ break;
+
+ case EXPECT_SOME:
+ if (cnt > 0)
+ printf ("PASS: %s/%s: expected some got %d\n", label, stage, cnt);
+ else
+ {
+ printf ("FAIL: %s/%s: expected some got 0\n", label, stage);
+ test_status = 1;
+ }
+ break;
+
+ case EXPECT_ALL:
+ if (cnt == PATTERN_REPS)
+ printf ("PASS: %s/%s: expected %d got %d\n", label, stage,
+ PATTERN_REPS, cnt);
+ else
+ {
+ printf ("FAIL: %s/%s: expected %d got %d\n", label, stage,
+ PATTERN_REPS, cnt);
+ test_status = 1;
+ }
+ break;
+
+ default:
+ printf ("ERROR: %s/%s: invalid value for 'expected' = %d\n",
+ label, stage, (int)expected);
+ test_status = 1;
+ }
+}
+
+static void
+test_loop (void)
+{
+ cur_subtest = subtests;
+ while (cur_subtest->setup_subtest)
+ {
+ if (swapcontext (&uc_main, &uc_co))
+ abort ();
+ check_test_buffer (EXPECT_ALL, cur_subtest->label, "prepare");
+ if (swapcontext (&uc_main, &uc_co))
+ abort ();
+ check_test_buffer (cur_subtest->expected, cur_subtest->label, "test");
+ cur_subtest++;
+ }
+ /* Terminate the coroutine. */
+ if (swapcontext (&uc_main, &uc_co))
+ abort ();
+}
+
+static int
+do_test (void)
+{
+ size_t page_alignment = sysconf (_SC_PAGESIZE);
+ if (page_alignment < sizeof (void *))
+ page_alignment = sizeof (void *);
+
+ co_stack_size = SIGSTKSZ + TEST_BUFFER_SIZE;
+ if (co_stack_size < page_alignment * 4)
+ co_stack_size = page_alignment * 4;
+
+ void *p;
+ int err = posix_memalign (&p, page_alignment, co_stack_size);
+ if (err || !p)
+ {
+ printf ("ERROR: allocating alt stack: %s\n", strerror (err));
+ return 2;
+ }
+ co_stack_buffer = p;
+
+ if (getcontext (&uc_co))
+ {
+ printf ("ERROR: allocating coroutine context: %s\n", strerror (err));
+ return 2;
+ }
+ uc_co.uc_stack.ss_sp = co_stack_buffer;
+ uc_co.uc_stack.ss_size = co_stack_size;
+ uc_co.uc_link = &uc_main;
+ makecontext (&uc_co, test_coroutine, 0);
+
+ test_loop ();
+ return test_status;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index 807e43d..b074374 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1843,6 +1843,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 gnu_dev_major F
GLIBC_2.25 gnu_dev_makedev F
GLIBC_2.25 gnu_dev_minor F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 77accdf..e265325 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2090,6 +2090,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 659b7fc..393dd4c 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2001,6 +2001,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 8bc979a..b92eccb 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -91,6 +91,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 299b705..3b1661d 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1855,6 +1855,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index f00345f..452e013 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2013,6 +2013,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index e5fcf88..0196234 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1877,6 +1877,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 8f382f6..d6e0e16 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -92,6 +92,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 320b7fe..c3a5f24 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1969,6 +1969,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 21b1426..fa72a0d 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2090,6 +2090,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 5c4b596..03d3c0c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1944,6 +1944,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 001fa6c..a1c9cd2 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1942,6 +1942,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 2d87001..a8671ba 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1940,6 +1940,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index aa1ee66..e71283f 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1935,6 +1935,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 2471d68..f92545c 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2131,6 +2131,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 4ba3146..1748455 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1973,6 +1973,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 0557c16..fa26199 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1978,6 +1978,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 821384e..73488a4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2178,6 +2178,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index c40a3f1..ac9cc69 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -92,6 +92,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 5b39a60..933a00a 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1973,6 +1973,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index a9db32f..eb74169 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1874,6 +1874,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 294af0a..37aded2 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1859,6 +1859,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 32747bd..5b7c54e 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1965,6 +1965,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index b0ac4d4..4854351 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1903,6 +1903,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index 4d92d81..18f61ba 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2097,6 +2097,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index a68aef7..53a0db1 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2097,6 +2097,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index 4d92d81..18f61ba 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2097,6 +2097,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index b8623fc..d4add67 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1854,6 +1854,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index a61d874..18717fa 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2097,6 +2097,9 @@ GLIBC_2.23 fts64_set F
GLIBC_2.24 GLIBC_2.24 A
GLIBC_2.24 quick_exit F
GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __explicit_bzero F
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.25 strfromd F
GLIBC_2.25 strfromf F
GLIBC_2.25 strfroml F
-----------------------------------------------------------------------
hooks/post-receive
--
GNU C Library master sources