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-80-g4d7aa37
- From: zack at sourceware dot org
- To: glibc-cvs at sourceware dot org
- Date: 19 Aug 2016 13:06:55 -0000
- Subject: GNU C Library master sources branch zack/explicit-bzero created. glibc-2.24-80-g4d7aa37
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 4d7aa37af287c8d44a46392c5fb260470a606533 (commit)
- Log -----------------------------------------------------------------
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4d7aa37af287c8d44a46392c5fb260470a606533
commit 4d7aa37af287c8d44a46392c5fb260470a606533
Author: Zack Weinberg <zackw@panix.com>
Date: Thu Aug 18 12:22:55 2016 -0400
Add a test for explicit_bzero not getting optimized out.
Conceptually based on a test written by Matthew Dempsky for the OpenBSD
regression suite.
* string/tst-xbzero-opt.c: New test.
* string/Makefile: Run it.
diff --git a/string/Makefile b/string/Makefile
index 180ec86..be7154b 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -60,7 +60,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \
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-strtok_r bug-strcoll2 tst-xbzero-opt
xtests = tst-strcoll-overflow
diff --git a/string/tst-xbzero-opt.c b/string/tst-xbzero-opt.c
new file mode 100644
index 0000000..81eb5c1
--- /dev/null
+++ b/string/tst-xbzero-opt.c
@@ -0,0 +1,383 @@
+/* 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 from a signal handler running on an alternative
+ signal stack. Then we have another pointer to the memory region
+ affected by the block clear -- namely, the sigaltstack buffer --
+ and can find out whether it actually happened.
+
+ The OpenBSD test cautions that some operating systems (e.g. Solaris
+ and OSX) wipe the signal stack upon returning to the normal stack,
+ so the test has to happen while still executing on the signal
+ stack. This, of course, means that the buffer might be clobbered
+ by normal stack operations after the function with the block clear
+ returns (it has to return, so that the block is truly dead). The
+ most straightforward way to deal with this is to have a large block
+ containing several copies of a byte pattern that is unlikely to
+ occur by chance, and check whether _any_ of them survives. */
+
+#define _GNU_SOURCE 1
+
+#include <stdbool.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* The "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
+};
+
+#define PATTERN_SIZE (sizeof test_pattern)
+#define PATTERN_REPS 32
+#define TEST_BUFFER_SIZE (PATTERN_SIZE * PATTERN_REPS)
+
+static void
+fill_with_test_pattern (unsigned char *buf)
+{
+ for (unsigned int i = 0; i < PATTERN_REPS; i++)
+ memcpy (buf + i*PATTERN_SIZE, test_pattern, PATTERN_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;
+}
+
+/* Global test state. */
+static int failed_subtests;
+static bool this_subtest_failed;
+
+/* The signal stack is allocated with memalign. */
+static unsigned char *signal_stack_buffer;
+#define SIGNAL_STACK_SIZE (SIGSTKSZ + TEST_BUFFER_SIZE)
+
+enum test_expectation { EXPECT_NONE, EXPECT_SOME, EXPECT_ALL };
+
+static void
+check_test_buffer (enum test_expectation expected,
+ const char *label, const char *stage)
+{
+ unsigned int cnt = count_test_patterns (signal_stack_buffer,
+ SIGNAL_STACK_SIZE);
+ switch (expected)
+ {
+ case EXPECT_NONE:
+ if (cnt == 0)
+ {
+ printf ("PASS: %s/%s: expected 0 got %d\n", label, stage, cnt);
+ fflush (stdout);
+ }
+ else
+ {
+ printf ("FAIL: %s/%s: expected 0 got %d\n", label, stage, cnt);
+ fflush (stdout);
+ this_subtest_failed = true;
+ failed_subtests++;
+ }
+ break;
+
+ case EXPECT_SOME:
+ if (cnt > 0)
+ {
+ printf ("PASS: %s/%s: expected some got %d\n", label, stage, cnt);
+ fflush (stdout);
+ }
+ else
+ {
+ printf ("FAIL: %s/%s: expected some got 0\n", label, stage);
+ fflush (stdout);
+ this_subtest_failed = true;
+ failed_subtests++;
+ }
+ break;
+
+ case EXPECT_ALL:
+ if (cnt == PATTERN_REPS)
+ {
+ printf ("PASS: %s/%s: expected %d got %d\n", label, stage,
+ PATTERN_REPS, cnt);
+ fflush (stdout);
+ }
+ else
+ {
+ printf ("FAIL: %s/%s: expected %d got %d\n", label, stage,
+ PATTERN_REPS, cnt);
+ fflush (stdout);
+ this_subtest_failed = true;
+ failed_subtests++;
+ }
+ break;
+
+ default:
+ printf ("ERROR: %s/%s: invalid value for 'expected' = %d\n",
+ label, stage, (int)expected);
+ fflush (stdout);
+ this_subtest_failed = true;
+ failed_subtests++;
+ }
+}
+
+/* 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, const char *label)
+{
+ fill_with_test_pattern (buf);
+ check_test_buffer (EXPECT_ALL, label, "prepare");
+
+ unsigned char *loc = memmem (signal_stack_buffer, SIGNAL_STACK_SIZE,
+ test_pattern, PATTERN_SIZE);
+ if (loc == buf)
+ {
+ printf ("PASS: %s/prepare: expected buffer location %p got %p\n",
+ label, buf, loc);
+ fflush (stdout);
+ }
+ else
+ {
+ printf ("FAIL: %s/prepare: expected buffer location %p got %p\n",
+ label, buf, loc);
+ fflush (stdout);
+ this_subtest_failed = true;
+ failed_subtests++;
+ }
+}
+
+/* There are three subtests, two of which are sanity checks.
+
+ 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 void
+setup_no_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf, "no clear");
+}
+
+static void
+setup_ordinary_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf, "ordinary clear");
+ if (this_subtest_failed)
+ return;
+ memset (buf, 0, TEST_BUFFER_SIZE);
+}
+
+static void
+setup_explicit_clear (void)
+{
+ unsigned char buf[TEST_BUFFER_SIZE];
+ prepare_test_buffer (buf, "explicit clear");
+ if (this_subtest_failed)
+ return;
+ explicit_bzero (buf, TEST_BUFFER_SIZE);
+}
+
+struct subtest
+{
+ void (*setup_subtest) (void);
+ const char *label;
+ enum test_expectation expected;
+};
+
+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 const struct subtest *this_subtest;
+static bool this_subtest_complete;
+
+/* This function is called as a signal handler. The signal is
+ triggered by a call to raise, therefore it is safe to do
+ non-async-signal-safe things within this function.
+
+ The this_subtest_complete flag addresses a race. The outer loop
+ keeps SIGUSR1 blocked all the time, unblocking it only immediately
+ after setting up the appropriate conditions for a test and then
+ raising SIGUSR1 itself. SIGUSR1 is not a real-time signal, so if
+ another process sends this process SIGUSR1 _before_ it's unblocked
+ by the outer loop, this function will only be called once.
+ However, if another process sends this process SIGUSR1 _while this
+ handler is already running_, that signal will be pending upon
+ return from this function, and will fire before the outer loop has
+ a chance to re-block SIGUSR1. This is unavoidable; the workaround
+ is to arrange for this function not to do anything if it's called
+ several times in a row. */
+static void
+do_subtest (int signo __attribute__ ((unused)))
+{
+ if (!this_subtest_complete)
+ {
+ this_subtest->setup_subtest ();
+ if (!this_subtest_failed)
+ check_test_buffer (this_subtest->expected,
+ this_subtest->label,
+ "test");
+ this_subtest_complete = true;
+ }
+}
+
+static int
+do_test (void)
+{
+ /* test-skeleton.c unconditionally sets stdout to be unbuffered.
+ vfprintf allocates a great deal of memory on the stack if called
+ with an unbuffered FILE*, overflowing the alt-stack. This is
+ also why there is a call to fflush after every call to printf in
+ this file. */
+ if (setvbuf (stdout, 0, _IOFBF, 0))
+ {
+ printf ("ERROR: restoring stdout buffering: %s\n", strerror (errno));
+ fflush (stdout);
+ return 2;
+ }
+
+ size_t page_alignment = sysconf (_SC_PAGESIZE);
+ if (page_alignment < sizeof (void *))
+ page_alignment = sizeof (void *);
+
+ void *p;
+ int err = posix_memalign (&p, page_alignment, SIGNAL_STACK_SIZE);
+ if (err || !p)
+ {
+ printf ("ERROR: allocating alt stack: %s\n", strerror (err));
+ fflush (stdout);
+ return 2;
+ }
+ signal_stack_buffer = p;
+
+ /* This program will malfunction if it receives SIGUSR1 signals at any
+ time other than when it's just sent one to itself. Therefore, keep
+ it blocked most of the time. */
+ sigset_t sigusr1_mask;
+ sigemptyset (&sigusr1_mask);
+ sigaddset (&sigusr1_mask, SIGUSR1);
+ if (sigprocmask (SIG_BLOCK, &sigusr1_mask, 0))
+ {
+ printf ("ERROR: block(SIGUSR1): %s\n", strerror (errno));
+ fflush (stdout);
+ return 2;
+ }
+
+ stack_t ss;
+ ss.ss_sp = signal_stack_buffer;
+ ss.ss_flags = 0;
+ ss.ss_size = SIGNAL_STACK_SIZE;
+ if (sigaltstack (&ss, 0))
+ {
+ printf ("ERROR: sigaltstack: %s\n", strerror (errno));
+ fflush (stdout);
+ return 2;
+ }
+
+ struct sigaction sa;
+ sigemptyset (&sa.sa_mask);
+ sigaddset (&sa.sa_mask, SIGUSR1);
+ sa.sa_handler = do_subtest;
+ sa.sa_flags = SA_RESTART | SA_ONSTACK;
+ if (sigaction (SIGUSR1, &sa, 0))
+ {
+ printf ("ERROR: sigaction(SIGUSR1): %s\n", strerror (errno));
+ fflush (stdout);
+ return 2;
+ }
+
+ /* We use kill instead of raise, because raise screws with the
+ signal mask, which we don't want. */
+ pid_t self = getpid ();
+
+ this_subtest = subtests;
+ while (this_subtest->label)
+ {
+ this_subtest_complete = false;
+ this_subtest_failed = false;
+
+ /* Completely clear the signal stack between tests, so that junk
+ from previous tests cannot interfere with the current one. */
+ memset (signal_stack_buffer, 0, SIGNAL_STACK_SIZE);
+
+ /* Raise SIGUSR1, then unblock it, then immediately block it
+ again. This will trigger do_subtest to run _once_ on the
+ alternative stack, at the point of calling sigprocmask to
+ unblock the signal. */
+ if (kill (self, SIGUSR1))
+ {
+ printf ("ERROR: raise(SIGUSR1): %s\n", strerror (errno));
+ fflush (stdout);
+ return 2;
+ }
+ if (sigprocmask (SIG_UNBLOCK, &sigusr1_mask, 0))
+ {
+ printf ("ERROR: unblock(SIGUSR1): %s\n", strerror (errno));
+ fflush (stdout);
+ return 2;
+ }
+ if (sigprocmask (SIG_BLOCK, &sigusr1_mask, 0))
+ {
+ printf ("ERROR: unblock(SIGUSR1): %s\n", strerror(errno));
+ fflush (stdout);
+ return 2;
+ }
+
+ this_subtest++;
+ }
+
+ return failed_subtests ? 1 : 0;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
http://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=3b9131ac3b2cd2c0d12bde98ad1aa4716d757336
commit 3b9131ac3b2cd2c0d12bde98ad1aa4716d757336
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..09a5664 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..6125c7f 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 ca703de..6717e22 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 c42e5b7..1965191 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=bedc31bbaaa76db47257ba93501b0e8c7df27c2d
commit bedc31bbaaa76db47257ba93501b0e8c7df27c2d
Author: Zack Weinberg <zackw@panix.com>
Date: Wed Aug 17 12:44:37 2016 -0400
Add fortification support for explicit_bzero.
The __glibc_read_memory approach means that this is very easy - it can
be defined in terms of __memset_chk, which was not possible in the previous
iteration.
* string/bits/string3.h: Fortify explicit_bzero.
* string/bits/string2.h: Cooperate with this.
* 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 f890585..f7fc866 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -57,7 +57,7 @@
# define __bzero(s, n) __builtin_memset (s, '\0', n)
#endif
-#ifdef __USE_MISC
+#if defined __USE_MISC && !defined __fortify_function
/* As bzero, but the compiler will not delete a call to this
function, even if S is dead after the call. Note: this function
has its own implementation file and should not be slurped into
diff --git a/string/bits/string3.h b/string/bits/string3.h
index dd8db68..d340bef 100644
--- a/string/bits/string3.h
+++ b/string/bits/string3.h
@@ -102,6 +102,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=0b79bf39354c1a5ee4878aea442d5a9ad4e5b64a
commit 0b79bf39354c1a5ee4878aea442d5a9ad4e5b64a
Author: Zack Weinberg <zackw@panix.com>
Date: Wed Aug 17 12:03:40 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.)
* string/explicit_bzero.c, string/read_memory.c: New routines.
* string/test-explicit_bzero.c: New test.
* string/Makefile (routines, strop-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.
* string/bits/string2.h [__USE_MISC]: Provide inline version of
explicit_bzero.
* manual/string.texi: Document explicit_bzero.
* string/Versions [GLIBC_2.25]: Add explicit_bzero and
__glibc_read_memory.
* include/string.h: Hidden prototype for __internal_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 and __glibc_read_memory.
diff --git a/include/string.h b/include/string.h
index e145bfd..277c07d 100644
--- a/include/string.h
+++ b/include/string.h
@@ -99,6 +99,8 @@ libc_hidden_proto (memmem)
extern __typeof (memmem) __memmem;
libc_hidden_proto (__memmem)
libc_hidden_proto (__ffs)
+extern __typeof (__glibc_read_memory) __internal_glibc_read_memory;
+libc_hidden_proto (__internal_glibc_read_memory)
libc_hidden_builtin_proto (memchr)
libc_hidden_builtin_proto (memcpy)
diff --git a/manual/string.texi b/manual/string.texi
index bce81a7..fe4ca48 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.
@@ -2375,6 +2377,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
+
+It is sometimes necessary to make sure that a block of data in memory
+is erased after use, even if no correct C program could access it
+again. For instance, a cryptographic key should not be allowed to
+survive on the stack after the program is finished using it, because
+there might be a bug that causes junk stack data, including the key,
+to be revealed to the outside world. @code{memset} and @code{bzero}
+are not safe to use for this, because the C compiler knows what they
+do, and can delete ``unnecessary'' calls to them. For this situation,
+@theglibc{} provides @code{explicit_bzero}, which is functionally
+identical to @code{bzero}, except that the C compiler will @emph{not}
+delete apparently-unnecessary calls.
+
+@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 each of the first @var{len}
+bytes of the object beginning at @var{block}, just as @code{bzero}
+would. The compiler will not delete a call to this function, even
+if the object beginning at @var{block} is never referred to again.
+
+@smallexample
+#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 smallexample
+
+@noindent
+If @code{bzero} or @code{memset} had been used in this function, the C
+compiler might remove it as unnecessary, but it will not do this with
+@code{explicit_bzero}.
+
+@strong{Warning:} The @emph{only} optimization disabled by
+@code{explicit_bzero} is removal of ``unnecessary'' calls. In all
+other respects, the compiler is allowed to optimize as it would for
+@code{memset}. For instance, it may deduce that @var{block} cannot be
+a null pointer, and propagate this information both forward and
+backward in control flow.
+
+@strong{Warning:} The compiler is free to make additional copies of
+any object, or parts of it, in temporary storage areas (such as
+registers and ``scratch'' stack space). @code{explicit_bzero} does
+not guarantee that temporary copies of sensitive data are destroyed.
+In fact, in some situations, using @code{explicit_bzero} will
+@emph{cause} creation of an additional copy, and only that copy will
+be cleared:
+
+@smallexample
+#include <string.h>
+
+struct key @{
+ unsigned long long low;
+ unsigned long long high;
+@};
+
+struct key get_key(void);
+void use_key(struct key);
+
+void
+with_clear(void)
+@{
+ struct key k;
+ k = get_key();
+ use_key(k);
+ explicit_bzero(&k, sizeof(k));
+@}
+@end smallexample
+
+@noindent
+Without the call to @code{explicit_bzero}, @var{k} might not need to
+be stored in memory: depending on the ABI, its value could be returned
+from @code{get_key} and passed to @code{use_key} using only CPU
+registers. @code{explicit_bzero} operates on memory, so the compiler
+has to make a copy of @var{k} in memory for it, and the copy in the
+CPU registers remains intact. This can occur for any variable whose
+address is only taken in a call to @code{explicit_bzero}, even if it
+might seem ``too large'' to be stored in registers.
+
+@strong{Portability Note:} This function first appeared in OpenBSD 5.5
+and has not been standardized. @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 9c87419..180ec86 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -41,13 +41,19 @@ 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 \
diff --git a/string/Versions b/string/Versions
index 475c1fd..b5c24f4 100644
--- a/string/Versions
+++ b/string/Versions
@@ -82,4 +82,11 @@ libc {
}
GLIBC_2.24 {
}
+ GLIBC_2.25 {
+ # used by inlines in string2.h
+ __glibc_read_memory;
+
+ # e*
+ explicit_bzero;
+ }
}
diff --git a/string/bits/string2.h b/string/bits/string2.h
index 8098760..f890585 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -52,11 +52,23 @@
#define __string2_1bptr_p(__x) \
((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1)
-/* Set N bytes of S to C. */
+/* Set N bytes of S to 0. */
#if !defined _HAVE_STRING_ARCH_memset
# define __bzero(s, n) __builtin_memset (s, '\0', n)
#endif
+#ifdef __USE_MISC
+/* As bzero, but the compiler will not delete a call to this
+ function, even if S is dead after the call. Note: this function
+ has its own implementation file and should not be slurped into
+ string-inlines.o. */
+__extern_inline void
+explicit_bzero (void *__s, size_t __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/explicit_bzero.c b/string/explicit_bzero.c
new file mode 100644
index 0000000..a02be4f
--- /dev/null
+++ b/string/explicit_bzero.c
@@ -0,0 +1,30 @@
+/* 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
+explicit_bzero (void *s, size_t len)
+{
+ memset (s, '\0', len);
+ __internal_glibc_read_memory (s, len);
+}
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 57deaa4..40851b5 100644
--- a/string/string.h
+++ b/string/string.h
@@ -455,6 +455,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 inline version 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/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index 4d3b0b9..02d4bc6 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1843,6 +1843,8 @@ 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 __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 2c2f49e..44dc0d1 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2090,3 +2090,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 8afba47..02a490d 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2001,6 +2001,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index de3bdf4..d2b2800 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -91,6 +91,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.4 GLIBC_2.4 A
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3261b93..59b2591 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1855,6 +1855,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 6465a55..e64f9c6 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2013,6 +2013,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 4536271..78acf45 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1877,6 +1877,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 287d7a5..ceb1909 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -92,6 +92,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.4 GLIBC_2.4 A
GLIBC_2.4 _Exit F
GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index c9229fa..e8d7256 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1969,6 +1969,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 0409791..c2e2ecc 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2090,3 +2090,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index f31653e..705f00b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1944,6 +1944,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index a56bd99..41d3e5c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1942,6 +1942,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 44552df..4de5839 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1940,6 +1940,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 8d2a09d..e1d5bec 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1935,6 +1935,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 0443b92..34e83a6 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2131,3 +2131,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index ba9a29a..91a30c8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1973,6 +1973,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index f19534c..a4ecbc2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1978,6 +1978,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index f8de1ab..277ec26 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2178,3 +2178,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 6819133..e3dafa5 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -92,6 +92,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 _Exit F
GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 4cd5d85..3ab826d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1973,6 +1973,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 8cdb9df..c4c0a8e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1874,6 +1874,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 69791b4..7a11b8a 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1859,6 +1859,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index fce58a8..13efb9f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1965,6 +1965,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 16ce739..da6819b 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1903,6 +1903,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index f99c298..0d58dc0 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2097,3 +2097,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index c601ab0..fc55930 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2097,3 +2097,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index f99c298..0d58dc0 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2097,3 +2097,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 8e6fa57..858a26c 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1854,6 +1854,8 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
GLIBC_2.3 GLIBC_2.3 A
GLIBC_2.3 __ctype_b_loc F
GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 1e12f48..9a45eed 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2097,3 +2097,5 @@ 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 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
-----------------------------------------------------------------------
hooks/post-receive
--
GNU C Library master sources