This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v3] explicit_bzero yet again


I've updated the explicit_bero patches for the change to how .abilist
files work and the reorganization of x86.  I've also split the
controversial string2.h optimization into its own patch so it can be
discussed separately from the merits of the interface.

zw
[PATCH 1/3] New library function, explicit_bzero

The new function explicit_bzero is functionally identical to bzero,
but the compiler will not delete a call to it, even if the memory
region it's applied to is dead after the call.  You should use this
function, for instance, to erase cryptographic keys or similar when
you are done with them.  Taken from OpenBSD.

	* manual/string.texi: Document new function explicit_bzero.

	* string/Versions [GLIBC_2.23]: Add explicit_bzero.
	* string/string.h [__USE_MISC]: Declare explicit_bzero.
	* string/bits/string3.h: Fortify explicit_bzero.
	* string/test-explicit_bzero.c: New file, basic test for
        explicit_bzero.
	* string/Makefile, string/test-memset.c: Support the new test.

	* string/bzero.c
	* sysdeps/alpha/bzero.S
	* sysdeps/i386/bzero.S
	* sysdeps/i386/i586/bzero.S
	* sysdeps/i386/i686/bzero.S
	* sysdeps/powerpc/powerpc32/bzero.S
	* sysdeps/powerpc/powerpc32/power4/multiarch/bzero.c
	* sysdeps/powerpc/powerpc64/memset.S
	* sysdeps/powerpc/powerpc64/multiarch/bzero.c
	* sysdeps/powerpc/powerpc64/power4/memset.S
	* sysdeps/powerpc/powerpc64/power6/memset.S
	* sysdeps/powerpc/powerpc64/power7/memset.S
	* sysdeps/powerpc/powerpc64/power8/memset.S
	* sysdeps/s390/s390-32/bzero.S
	* sysdeps/s390/s390-64/bzero.S
	* sysdeps/sparc/sparc32/memset.S
	* sysdeps/sparc/sparc64/memset.S
	* sysdeps/sparc/sparc64/multiarch/memset.S
	* sysdeps/tile/bzero.S
	* sysdeps/x86_64/memset.S:
	Declare explicit_bzero as weak alias of __bzero.

	* debug/explicit_bzero_chk.c: New file.
	* debug/Makefile: Compile it.
	* debug/Versions [GLIBC_2.23]: Add __explicit_bzero_chk.
	* debug/tst-chk1.c: Test fortification of explicit_bzero,
        and also bzero and bcopy, while we're at it.

	* include/string.h: Add libc_hidden_proto for __memset_chk.
	* debug/memset_chk.c: Add libc_hidden_def for __memset_chk.
	En passant, remove unnecessary #include.
	* sysdeps/i386/i586/memset.S
	* sysdeps/i386/i686/memset.S
	* sysdeps/i386/i686/multiarch/memset.S
	* sysdeps/x86_64/memset.S
	* sysdeps/x86_64/multiarch/memset.S:
	Add libc_hidden_builtin_def for __memset_chk.

	* 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.abilist
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.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 explicit_bzero and __explicit_bzero_chk to GLIBC_2.23.
---
 debug/Makefile                                     |   1 +
 debug/Versions                                     |   3 +
 debug/explicit_bzero_chk.c                         |  28 ++++++
 debug/memset_chk.c                                 |   2 +-
 debug/tst-chk1.c                                   |  89 ++++++++++++++++++
 include/string.h                                   |   4 +
 manual/string.texi                                 | 101 +++++++++++++++++++++
 string/Makefile                                    |   3 +-
 string/Versions                                    |   3 +
 string/bits/string3.h                              |  18 ++++
 string/bzero.c                                     |   1 +
 string/string.h                                    |   4 +
 string/test-explicit_bzero.c                       |  21 +++++
 string/test-memset.c                               |  10 +-
 sysdeps/alpha/bzero.S                              |   1 +
 sysdeps/arm/nacl/libc.abilist                      |   3 +
 sysdeps/i386/bzero.S                               |   1 +
 sysdeps/i386/i586/bzero.S                          |   1 +
 sysdeps/i386/i586/memset.S                         |   1 +
 sysdeps/i386/i686/bzero.S                          |   1 +
 sysdeps/i386/i686/memset.S                         |   1 +
 sysdeps/i386/i686/multiarch/memset.S               |   8 +-
 sysdeps/i386/memset.S                              |   1 +
 sysdeps/powerpc/powerpc32/bzero.S                  |   1 +
 sysdeps/powerpc/powerpc32/power4/multiarch/bzero.c |   1 +
 sysdeps/powerpc/powerpc64/memset.S                 |   1 +
 sysdeps/powerpc/powerpc64/multiarch/bzero.c        |   1 +
 sysdeps/powerpc/powerpc64/power4/memset.S          |   1 +
 sysdeps/powerpc/powerpc64/power6/memset.S          |   1 +
 sysdeps/powerpc/powerpc64/power7/memset.S          |   1 +
 sysdeps/powerpc/powerpc64/power8/memset.S          |   1 +
 sysdeps/s390/s390-32/bzero.S                       |   1 +
 sysdeps/s390/s390-64/bzero.S                       |   1 +
 sysdeps/sparc/sparc32/memset.S                     |   1 +
 sysdeps/sparc/sparc64/memset.S                     |   1 +
 sysdeps/sparc/sparc64/multiarch/memset.S           |   1 +
 sysdeps/tile/bzero.S                               |   1 +
 sysdeps/unix/sysv/linux/aarch64/libc.abilist       |   2 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   2 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   2 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   2 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   2 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   2 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   2 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   2 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   2 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   2 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   2 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   2 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   2 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   2 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   2 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   2 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   2 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   2 +
 sysdeps/x86_64/memset.S                            |   2 +
 sysdeps/x86_64/multiarch/memset.S                  |   6 +-
 67 files changed, 375 insertions(+), 9 deletions(-)
 create mode 100644 debug/explicit_bzero_chk.c
 create mode 100644 string/test-explicit_bzero.c

diff --git a/debug/Makefile b/debug/Makefile
index a383417..9c42fc2 100644
--- a/debug/Makefile
+++ b/debug/Makefile
@@ -29,6 +29,7 @@ headers	:= execinfo.h
 # build, its _FORTIFY_SOURCE support will be too.
 routines  = backtrace backtracesyms backtracesymsfd noophooks \
 	    memcpy_chk memmove_chk mempcpy_chk memset_chk stpcpy_chk \
+	    explicit_bzero_chk \
 	    strcat_chk strcpy_chk strncat_chk strncpy_chk stpncpy_chk \
 	    sprintf_chk vsprintf_chk snprintf_chk vsnprintf_chk \
 	    printf_chk fprintf_chk vprintf_chk vfprintf_chk \
diff --git a/debug/Versions b/debug/Versions
index 0482c85..3c7feb1 100644
--- a/debug/Versions
+++ b/debug/Versions
@@ -55,6 +55,9 @@ libc {
   GLIBC_2.16 {
     __poll_chk; __ppoll_chk;
   }
+  GLIBC_2.23 {
+    __explicit_bzero_chk;
+  }
   GLIBC_PRIVATE {
     __fortify_fail;
   }
diff --git a/debug/explicit_bzero_chk.c b/debug/explicit_bzero_chk.c
new file mode 100644
index 0000000..574802d
--- /dev/null
+++ b/debug/explicit_bzero_chk.c
@@ -0,0 +1,28 @@
+/* Copyright (C) 1991-2015 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 has to be an exported symbol, unlike plain bzero, because
+   bits/string3.h cannot use __memset_chk as it does for checked
+   bzero.  See "Erasing Sensitive Data" in the manual.  */
+
+void
+__explicit_bzero_chk (void *dstpp, size_t len, size_t dstlen)
+{
+  (void) __memset_chk (dstpp, 0, len, dstlen);
+}
diff --git a/debug/memset_chk.c b/debug/memset_chk.c
index 43003b5..4df7c45 100644
--- a/debug/memset_chk.c
+++ b/debug/memset_chk.c
@@ -16,7 +16,6 @@
    <http://www.gnu.org/licenses/>.  */
 
 #include <string.h>
-#include <memcopy.h>
 
 void *
 __memset_chk (void *dstpp, int c, size_t len, size_t dstlen)
@@ -26,3 +25,4 @@ __memset_chk (void *dstpp, int c, size_t len, size_t dstlen)
 
   return memset (dstpp, c, len);
 }
+libc_hidden_def (__memset_chk)
diff --git a/debug/tst-chk1.c b/debug/tst-chk1.c
index bded583..4064eb9 100644
--- a/debug/tst-chk1.c
+++ b/debug/tst-chk1.c
@@ -143,6 +143,11 @@ do_test (void)
   if (memcmp (buf, "aabcdefghi", 10))
     FAIL ();
 
+  memcpy (buf, "abcdefghij", 10);
+  bcopy (buf, buf + 1, 9);
+  if (memcmp (buf, "aabcdefghi", 10))
+    FAIL ();
+
   if (mempcpy (buf + 5, "abcde", 5) != buf + 10
       || memcmp (buf, "aabcdabcde", 10))
     FAIL ();
@@ -151,6 +156,14 @@ do_test (void)
   if (memcmp (buf, "aabcdabcjj", 10))
     FAIL ();
 
+  bzero (buf + 8, 2);
+  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 ();
@@ -175,6 +188,11 @@ do_test (void)
   if (memcmp (buf, "aabcdefghi", 10))
     FAIL ();
 
+  memcpy (buf, "abcdefghij", l0 + 10);
+  bcopy (buf, buf + 1, l0 + 9);
+  if (memcmp (buf, "aabcdefghi", 10))
+    FAIL ();
+
   if (mempcpy (buf + 5, "abcde", l0 + 5) != buf + 10
       || memcmp (buf, "aabcdabcde", 10))
     FAIL ();
@@ -183,6 +201,14 @@ do_test (void)
   if (memcmp (buf, "aabcdabcjj", 10))
     FAIL ();
 
+  bzero (buf + 8, l0 + 2);
+  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 ();
@@ -214,11 +240,18 @@ do_test (void)
   if (memcmp (buf, "aabcEcdZY", 10))
     FAIL ();
 
+  /* The following tests are supposed to succeed at all fortify
+     levels, even though they overflow a.buf1 into a.buf2.  */
   memcpy (a.buf1, "abcdefghij", l0 + 10);
   memmove (a.buf1 + 1, a.buf1, l0 + 9);
   if (memcmp (a.buf1, "aabcdefghi", 10))
     FAIL ();
 
+  memcpy (a.buf1, "abcdefghij", l0 + 10);
+  bcopy (a.buf1, a.buf1 + 1, l0 + 9);
+  if (memcmp (a.buf1, "aabcdefghi", 10))
+    FAIL ();
+
   if (mempcpy (a.buf1 + 5, "abcde", l0 + 5) != a.buf1 + 10
       || memcmp (a.buf1, "aabcdabcde", 10))
     FAIL ();
@@ -227,6 +260,14 @@ do_test (void)
   if (memcmp (a.buf1, "aabcdabcjj", 10))
     FAIL ();
 
+  bzero (a.buf1 + 8, l0 + 2);
+  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
@@ -285,6 +326,14 @@ do_test (void)
   CHK_FAIL_END
 
   CHK_FAIL_START
+  bcopy (buf + 1, buf + 2, 9);
+  CHK_FAIL_END
+
+  CHK_FAIL_START
+  bcopy (buf + 1, buf + 2, l0 + 9);
+  CHK_FAIL_END
+
+  CHK_FAIL_START
   p = (char *) mempcpy (buf + 6, "abcde", 5);
   CHK_FAIL_END
 
@@ -301,6 +350,22 @@ do_test (void)
   CHK_FAIL_END
 
   CHK_FAIL_START
+  bzero (buf + 9, 2);
+  CHK_FAIL_END
+
+  CHK_FAIL_START
+  bzero (buf + 9, l0 + 2);
+  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
 
@@ -378,6 +443,14 @@ do_test (void)
   CHK_FAIL_END
 
   CHK_FAIL_START
+  bcopy (a.buf1 + 1, a.buf1 + 2, 9);
+  CHK_FAIL_END
+
+  CHK_FAIL_START
+  bcopy (a.buf1 + 1, a.buf1 + 2, l0 + 9);
+  CHK_FAIL_END
+
+  CHK_FAIL_START
   p = (char *) mempcpy (a.buf1 + 6, "abcde", 5);
   CHK_FAIL_END
 
@@ -393,6 +466,22 @@ do_test (void)
   memset (a.buf1 + 9, 'j', l0 + 2);
   CHK_FAIL_END
 
+  CHK_FAIL_START
+  bzero (a.buf1 + 9, 2);
+  CHK_FAIL_END
+
+  CHK_FAIL_START
+  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/include/string.h b/include/string.h
index a684fd9..a0909e3 100644
--- a/include/string.h
+++ b/include/string.h
@@ -180,6 +180,10 @@ extern char *__strcat_chk (char *__restrict __dest,
 extern char *__strncat_chk (char *__restrict __dest,
 			    const char *__restrict __src,
 			    size_t __len, size_t __destlen) __THROW;
+
+/* Used by __explicit_bzero_chk.  */
+libc_hidden_proto (__memset_chk)
+
 #endif
 
 #endif
diff --git a/manual/string.texi b/manual/string.texi
index 5f8a17e..f538fd5 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -33,6 +33,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.
@@ -2303,6 +2305,105 @@ contains no '/' characters, 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 ebe9354..c0e328c 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -47,7 +47,8 @@ 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 59bf35a..0a02884 100644
--- a/string/Versions
+++ b/string/Versions
@@ -80,4 +80,7 @@ libc {
   GLIBC_2.6 {
     strerror_l;
   }
+  GLIBC_2.23 {
+    explicit_bzero;
+  }
 }
diff --git a/string/bits/string3.h b/string/bits/string3.h
index 4d11aa6..8bef250 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,23 @@ __NTH (bzero (void *__dest, size_t __len))
 {
   (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
 }
+
+/* XXX We have no corresponding builtin yet. */
+
+extern void __explicit_bzero_chk (void *__dest, size_t __len, size_t __dstlen);
+extern void __REDIRECT_NTH (__explicit_bzero_alias,
+                            (void *__dest, size_t __len),
+                            explicit_bzero);
+
+__fortify_function void
+__NTH (explicit_bzero (void *__dest, size_t __len))
+{
+  if (__bos0 (__dest) != (size_t) -1
+      && (!__builtin_constant_p (__len) || __len > __bos0 (__dest)))
+    __explicit_bzero_chk (__dest, __len, __bos0 (__dest));
+  else
+    __explicit_bzero_alias (__dest, __len);
+}
 #endif
 
 __fortify_function char *
diff --git a/string/bzero.c b/string/bzero.c
index 43e2b38..d60f494 100644
--- a/string/bzero.c
+++ b/string/bzero.c
@@ -27,3 +27,4 @@ __bzero (void *s, size_t len)
   memset (s, '\0', len);
 }
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/string/string.h b/string/string.h
index 3ab7103..0df7789 100644
--- a/string/string.h
+++ b/string/string.h
@@ -453,6 +453,10 @@ 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));
+
 /* 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..8e354c7
--- /dev/null
+++ b/string/test-explicit_bzero.c
@@ -0,0 +1,21 @@
+/* Test and measure explicit_bzero.
+   Copyright (C) 2012-2015 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 79b2983..dae978c 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/alpha/bzero.S b/sysdeps/alpha/bzero.S
index e3c015a..582b85a 100644
--- a/sysdeps/alpha/bzero.S
+++ b/sysdeps/alpha/bzero.S
@@ -108,3 +108,4 @@ $done:	ret
 
 	cfi_endproc
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index 561441e..a7dcc1f 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1834,3 +1834,6 @@ GLIBC_2.22 wprintf F
 GLIBC_2.22 write F
 GLIBC_2.22 writev F
 GLIBC_2.22 wscanf F
+GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
diff --git a/sysdeps/i386/bzero.S b/sysdeps/i386/bzero.S
index c8dd47b..2f5641f 100644
--- a/sysdeps/i386/bzero.S
+++ b/sysdeps/i386/bzero.S
@@ -3,3 +3,4 @@
 #include "memset.S"
 
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/i386/i586/bzero.S b/sysdeps/i386/i586/bzero.S
index 2a10671..cb1bf0e 100644
--- a/sysdeps/i386/i586/bzero.S
+++ b/sysdeps/i386/i586/bzero.S
@@ -2,3 +2,4 @@
 #define memset __bzero
 #include <sysdeps/i386/i586/memset.S>
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/i386/i586/memset.S b/sysdeps/i386/i586/memset.S
index 82f7878..503f680 100644
--- a/sysdeps/i386/i586/memset.S
+++ b/sysdeps/i386/i586/memset.S
@@ -112,6 +112,7 @@ L(2):	shrl	$2, %ecx	/* convert byte count to longword count */
 	ret
 END (memset)
 libc_hidden_builtin_def (memset)
+libc_hidden_builtin_def (__memset_chk)
 
 #if defined SHARED && IS_IN (libc) && !defined __memset_chk \
     && !defined USE_AS_BZERO
diff --git a/sysdeps/i386/i686/bzero.S b/sysdeps/i386/i686/bzero.S
index c7898f1..5d674fa 100644
--- a/sysdeps/i386/i686/bzero.S
+++ b/sysdeps/i386/i686/bzero.S
@@ -2,3 +2,4 @@
 #define memset __bzero
 #include <sysdeps/i386/i686/memset.S>
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/i386/i686/memset.S b/sysdeps/i386/i686/memset.S
index 86c3010..7c641b0 100644
--- a/sysdeps/i386/i686/memset.S
+++ b/sysdeps/i386/i686/memset.S
@@ -91,6 +91,7 @@ ENTRY (memset)
 	ret
 END (memset)
 libc_hidden_builtin_def (memset)
+libc_hidden_builtin_def (__memset_chk)
 
 #if defined SHARED && IS_IN (libc) && !defined __memset_chk \
     && !defined USE_AS_BZERO
diff --git a/sysdeps/i386/i686/multiarch/memset.S b/sysdeps/i386/i686/multiarch/memset.S
index 8015d57..21b6220 100644
--- a/sysdeps/i386/i686/multiarch/memset.S
+++ b/sysdeps/i386/i686/multiarch/memset.S
@@ -63,9 +63,11 @@ END(memset)
 #  undef libc_hidden_builtin_def
 /* IFUNC doesn't work with the hidden functions in shared library since
    they will be called without setting up EBX needed for PLT which is
-   used by IFUNC.  */
-#  define libc_hidden_builtin_def(name) \
-	.globl __GI_memset; __GI_memset = __memset_ia32
+   used by IFUNC.  ../memset.S will barf if we #define memset, so we
+   must instead create the necessary __GI_ symbols manually.  */
+#  define libc_hidden_builtin_def(name) /* disable */
+        .globl __GI_memset; __GI_memset = __memset_ia32
+        .globl __GI___memset_chk; __GI__memset_chk = __memset_chk_ia32
 # endif
 
 # undef strong_alias
diff --git a/sysdeps/i386/memset.S b/sysdeps/i386/memset.S
index 21b3430..5ef8650 100644
--- a/sysdeps/i386/memset.S
+++ b/sysdeps/i386/memset.S
@@ -65,4 +65,5 @@ END (memset)
 
 #ifndef USE_AS_BZERO
 libc_hidden_builtin_def (memset)
+libc_hidden_builtin_def (__memset_chk)
 #endif
diff --git a/sysdeps/powerpc/powerpc32/bzero.S b/sysdeps/powerpc/powerpc32/bzero.S
index ae21c53..2f9614e 100644
--- a/sysdeps/powerpc/powerpc32/bzero.S
+++ b/sysdeps/powerpc/powerpc32/bzero.S
@@ -25,3 +25,4 @@ ENTRY (__bzero)
 	b	memset@local
 END (__bzero)
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/powerpc/powerpc32/power4/multiarch/bzero.c b/sysdeps/powerpc/powerpc32/power4/multiarch/bzero.c
index e938643..88aec9c 100644
--- a/sysdeps/powerpc/powerpc32/power4/multiarch/bzero.c
+++ b/sysdeps/powerpc/powerpc32/power4/multiarch/bzero.c
@@ -34,4 +34,5 @@ libc_ifunc (__bzero,
             : __bzero_ppc);
 
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/powerpc/powerpc64/memset.S b/sysdeps/powerpc/powerpc64/memset.S
index f8543e5..7acc1aa 100644
--- a/sysdeps/powerpc/powerpc64/memset.S
+++ b/sysdeps/powerpc/powerpc64/memset.S
@@ -258,4 +258,5 @@ ENTRY (__bzero)
 END_GEN_TB (__bzero,TB_TOCLESS)
 
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/powerpc/powerpc64/multiarch/bzero.c b/sysdeps/powerpc/powerpc64/multiarch/bzero.c
index 4953284..df10f36 100644
--- a/sysdeps/powerpc/powerpc64/multiarch/bzero.c
+++ b/sysdeps/powerpc/powerpc64/multiarch/bzero.c
@@ -40,4 +40,5 @@ libc_ifunc (__bzero,
             : __bzero_ppc);
 
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/powerpc/powerpc64/power4/memset.S b/sysdeps/powerpc/powerpc64/power4/memset.S
index 58877af..709db11 100644
--- a/sysdeps/powerpc/powerpc64/power4/memset.S
+++ b/sysdeps/powerpc/powerpc64/power4/memset.S
@@ -245,4 +245,5 @@ ENTRY (__bzero)
 END (__bzero)
 #ifndef __bzero
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/powerpc/powerpc64/power6/memset.S b/sysdeps/powerpc/powerpc64/power6/memset.S
index 02f279d..b49b0a8 100644
--- a/sysdeps/powerpc/powerpc64/power6/memset.S
+++ b/sysdeps/powerpc/powerpc64/power6/memset.S
@@ -389,4 +389,5 @@ ENTRY (__bzero)
 END (__bzero)
 #ifndef __bzero
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/powerpc/powerpc64/power7/memset.S b/sysdeps/powerpc/powerpc64/power7/memset.S
index 4c8c06f..adf4bfd 100644
--- a/sysdeps/powerpc/powerpc64/power7/memset.S
+++ b/sysdeps/powerpc/powerpc64/power7/memset.S
@@ -393,4 +393,5 @@ ENTRY (__bzero)
 END (__bzero)
 #ifndef __bzero
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/powerpc/powerpc64/power8/memset.S b/sysdeps/powerpc/powerpc64/power8/memset.S
index eaff0e6..6d2ca37 100644
--- a/sysdeps/powerpc/powerpc64/power8/memset.S
+++ b/sysdeps/powerpc/powerpc64/power8/memset.S
@@ -451,4 +451,5 @@ ENTRY (__bzero)
 END (__bzero)
 #ifndef __bzero
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/s390/s390-32/bzero.S b/sysdeps/s390/s390-32/bzero.S
index 7c03c3e..8a3c0cc 100644
--- a/sysdeps/s390/s390-32/bzero.S
+++ b/sysdeps/s390/s390-32/bzero.S
@@ -39,4 +39,5 @@ END(__bzero)
 
 #ifndef NO_WEAK_ALIAS
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/s390/s390-64/bzero.S b/sysdeps/s390/s390-64/bzero.S
index 355142b..3b72e50 100644
--- a/sysdeps/s390/s390-64/bzero.S
+++ b/sysdeps/s390/s390-64/bzero.S
@@ -38,4 +38,5 @@ END(__bzero)
 
 #ifndef NO_WEAK_ALIAS
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 #endif
diff --git a/sysdeps/sparc/sparc32/memset.S b/sysdeps/sparc/sparc32/memset.S
index 7021ce4..67a18f1 100644
--- a/sysdeps/sparc/sparc32/memset.S
+++ b/sysdeps/sparc/sparc32/memset.S
@@ -152,3 +152,4 @@ END(memset)
 libc_hidden_builtin_def (memset)
 
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/sparc/sparc64/memset.S b/sysdeps/sparc/sparc64/memset.S
index d3293fc..85a7a1f 100644
--- a/sysdeps/sparc/sparc64/memset.S
+++ b/sysdeps/sparc/sparc64/memset.S
@@ -312,3 +312,4 @@ ENTRY(__bzero)
 END(__bzero)
 
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/sparc/sparc64/multiarch/memset.S b/sysdeps/sparc/sparc64/multiarch/memset.S
index 45de5ab..ca26cb0 100644
--- a/sysdeps/sparc/sparc64/multiarch/memset.S
+++ b/sysdeps/sparc/sparc64/multiarch/memset.S
@@ -107,6 +107,7 @@ ENTRY(__bzero)
 END(__bzero)
 
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 
 # undef weak_alias
 # define weak_alias(a, b)
diff --git a/sysdeps/tile/bzero.S b/sysdeps/tile/bzero.S
index 412dc97..3472738 100644
--- a/sysdeps/tile/bzero.S
+++ b/sysdeps/tile/bzero.S
@@ -28,3 +28,4 @@ ENTRY(__bzero)
 	j __memset
 END(__bzero)
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 5799239..5f1a713 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2082,6 +2082,8 @@ GLIBC_2.18 _mcount F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 0fa4ee9..b01db61 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -1993,6 +1993,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index db9fa35..453110e 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -83,6 +83,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 1d30644..032a578 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1847,6 +1847,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 8f3502d..168b624 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2005,6 +2005,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 921ec55..83216bc 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1869,6 +1869,8 @@ GLIBC_2.2.6 getunwind F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 019095b..7025bdb 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -84,6 +84,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index a999a48..962b0af 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1961,6 +1961,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 0a08bba..df49f40 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2082,6 +2082,8 @@ GLIBC_2.18 xprt_unregister F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 2ab9e94..12370a2 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1936,6 +1936,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index b9b4b74..d259009 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1934,6 +1934,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 14e1236..9165211 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1932,6 +1932,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 53e0c9a..85e581e 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1927,6 +1927,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index dff1ee9..a2ed234 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2123,6 +2123,8 @@ GLIBC_2.21 xprt_unregister F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 6861846..031de90 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1965,6 +1965,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index fd611aa..e00c990 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1970,6 +1970,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index a97bd43..3427e99 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2170,6 +2170,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 00772cb..a7c3f87 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -84,6 +84,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 05cb85e..21f6372 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1965,6 +1965,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 1af185f..a0681d4 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1866,6 +1866,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index e128692..88a7f35 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1851,6 +1851,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index eb14113..1c8b024 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1957,6 +1957,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 91b97ef..04bf290 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1895,6 +1895,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index ffcc4a0..9bf29d9 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2089,6 +2089,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index a66e8ec..b5a14fa 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2089,6 +2089,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index ffcc4a0..9bf29d9 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2089,6 +2089,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index c6e3cd4..065afb1 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1846,6 +1846,8 @@ GLIBC_2.2.6 __nanosleep F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 04dc8e4..39326ee 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2089,6 +2089,8 @@ GLIBC_2.18 __cxa_thread_atexit_impl F
 GLIBC_2.22 GLIBC_2.22 A
 GLIBC_2.22 fmemopen F
 GLIBC_2.23 GLIBC_2.23 A
+GLIBC_2.23 __explicit_bzero_chk F
+GLIBC_2.23 explicit_bzero F
 GLIBC_2.23 fts64_children F
 GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
diff --git a/sysdeps/x86_64/memset.S b/sysdeps/x86_64/memset.S
index 3855cc8..c3152cb 100644
--- a/sysdeps/x86_64/memset.S
+++ b/sysdeps/x86_64/memset.S
@@ -28,6 +28,7 @@ ENTRY(__bzero)
 	jmp	L(entry_from_bzero)
 END(__bzero)
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 
 /* Like memset but takes additional parameter with return value.  */
 ENTRY(__memset_tail)
@@ -124,6 +125,7 @@ L(between8_16bytes):
 
 END (memset)
 libc_hidden_builtin_def (memset)
+libc_hidden_builtin_def (__memset_chk)
 
 #if defined PIC && IS_IN (libc) && !defined USE_MULTIARCH
 strong_alias (__memset_chk, __memset_zero_constant_len_parameter)
diff --git a/sysdeps/x86_64/multiarch/memset.S b/sysdeps/x86_64/multiarch/memset.S
index dbc00d2..274d7ed 100644
--- a/sysdeps/x86_64/multiarch/memset.S
+++ b/sysdeps/x86_64/multiarch/memset.S
@@ -42,12 +42,12 @@ END(memset)
 # define __memset_chk __memset_chk_sse2
 
 # ifdef SHARED
-# undef libc_hidden_builtin_def
+#  undef libc_hidden_builtin_def
 /* It doesn't make sense to send libc-internal memset calls through a PLT.
    The speedup we get from using GPR instruction is likely eaten away
    by the indirect call in the PLT.  */
-# define libc_hidden_builtin_def(name) \
-	.globl __GI_memset; __GI_memset = __memset_sse2
+#  define libc_hidden_builtin_def(name) \
+	.globl __GI_##name; __GI_##name = name
 # endif
 
 # undef strong_alias
-- 
2.6.2

[PATCH 2/3] Add string[23].h optimization of explicit_bzero.

This currently only works for gcc >=4.0 (and not clang) when compiling C.

        * string/bits/string2.h: Optimize explicit_bzero when possible.
        * string/bits/string3.h: Likewise.
---
 string/bits/string2.h | 30 +++++++++++++++++++++++++++++-
 string/bits/string3.h | 22 +++++++++++++++++++++-
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/string/bits/string2.h b/string/bits/string2.h
index 7645176..cc22e5c 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -194,7 +194,35 @@ __STRING2_COPY_TYPE (8);
 #  define __bzero(s, n) __builtin_memset (s, '\0', n)
 # endif
 
-#endif
+#endif /* !_HAVE_STRING_ARCH_memset */
+
+/* explicit_bzero can be optimized to memset plus a vacuous (but
+   non-deletable) use of the memory region, thus enabling all the
+   usual memset optimizations.
+
+   The __asm__ construct used below is known to work with GCC 4 and
+   later, when the size of the memory region is constant.  It's not
+   documented to work otherwise.  Moreover, even when guarded by
+   __builtin_constant_p, 'struct {char __x[n];}', where 'n' isn't
+   _syntactically_ an integer constant expression, is a hard error for
+   GCC when compiling C++, and a hard error for clang in both C and C++.  */
+
+#ifdef __USE_MISC
+# if __GNUC_PREREQ (4, 0) && !defined __clang__ && !defined __cplusplus
+__STRING_INLINE void
+__explicit_bzero_constn (void *__s, size_t __n)
+{
+  typedef struct {char __x[__n];} __memblk;
+  memset (__s, 0, __n);
+  __asm__ ("" : : "m" (*(__memblk __attribute__ ((__may_alias__)) *)__s));
+}
+
+#  define explicit_bzero(s, n)                          \
+  (__extension__ (__builtin_constant_p (n) && (n) > 0   \
+                  ? __explicit_bzero_constn (s, n)      \
+                  : explicit_bzero (s, n)))
+# endif
+#endif /* __USE_MISC */
 
 
 /* Copy N bytes from SRC to DEST, returning pointer to byte following the
diff --git a/string/bits/string3.h b/string/bits/string3.h
index 8bef250..a8ae700 100644
--- a/string/bits/string3.h
+++ b/string/bits/string3.h
@@ -104,7 +104,18 @@ __NTH (bzero (void *__dest, size_t __len))
   (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
 }
 
-/* XXX We have no corresponding builtin yet. */
+/* XXX We have no corresponding builtin yet.
+
+   __explicit_bzero_chk can be optimized to __builtin___memset_chk
+   plus a vacuous (but non-deletable) use of the memory region, thus
+   enabling all the usual memset optimizations.
+
+   The __asm__ construct used below is known to work with GCC 4 and
+   later, when the size of the memory region is constant.  It's not
+   documented to work otherwise.  Moreover, even when guarded by
+   __builtin_constant_p, 'struct {char __x[n];}', where 'n' isn't
+   _syntactically_ an integer constant expression, is a hard error for
+   GCC when compiling C++, and a hard error for clang in both C and C++.  */
 
 extern void __explicit_bzero_chk (void *__dest, size_t __len, size_t __dstlen);
 extern void __REDIRECT_NTH (__explicit_bzero_alias,
@@ -114,6 +125,15 @@ extern void __REDIRECT_NTH (__explicit_bzero_alias,
 __fortify_function void
 __NTH (explicit_bzero (void *__dest, size_t __len))
 {
+# if __GNUC_PREREQ (4, 0) && !defined __clang__ && !defined __cplusplus
+  if (__builtin_constant_p (__len) && __len > 0)
+    {
+      (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
+      typedef struct { char __x[__len]; } __memblk;
+      __asm__ ("" :: "m" (*(__memblk __attribute__ ((__may_alias__)) *)__dest));
+    }
+  else
+# endif
   if (__bos0 (__dest) != (size_t) -1
       && (!__builtin_constant_p (__len) || __len > __bos0 (__dest)))
     __explicit_bzero_chk (__dest, __len, __bos0 (__dest));
-- 
2.6.2

[PATCH 3/3] 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.
---
 crypt/crypt-entry.c  | 11 +++++++++++
 crypt/md5-crypt.c    |  8 ++++----
 crypt/sha256-crypt.c | 14 +++++++-------
 crypt/sha512-crypt.c | 14 +++++++-------
 4 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/crypt/crypt-entry.c b/crypt/crypt-entry.c
index f7b3949..1ea127e 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 dad5942..8063e87 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 96102e9..55c40dc 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 9257492..d3baafb 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);
-- 
2.6.2


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]