[RFC] explicit_bzero, again

Message ID 55F050D3.2070403@panix.com
State Superseded
Headers

Commit Message

Zack Weinberg Sept. 9, 2015, 3:31 p.m. UTC
  This updated patchset adds to the manual discussion of the situation
where using explicit_bzero *creates* a copy of sensitive data in memory,
which would not otherwise have been created.  There are no changes to
the code.  Earlier discussion with Florian and Adhemerval explored some
possible alternative implementation strategies but reached the
conclusion that this really is the best we can do without compiler support.

zw
  

Comments

Zack Weinberg Sept. 15, 2015, 2:21 p.m. UTC | #1
Ping.

On Wed, Sep 9, 2015 at 11:31 AM, Zack Weinberg <zackw@panix.com> wrote:
> This updated patchset adds to the manual discussion of the situation
> where using explicit_bzero *creates* a copy of sensitive data in memory,
> which would not otherwise have been created.  There are no changes to
> the code.  Earlier discussion with Florian and Adhemerval explored some
> possible alternative implementation strategies but reached the
> conclusion that this really is the best we can do without compiler support.
>
> zw
  
Adhemerval Zanella Netto Sept. 15, 2015, 2:49 p.m. UTC | #2
At first I was convinced that adding this symbol would be a good approach,
but after reading comments from Rick Felker and Szabolcs Nagy I am not sure
any more.

Besides the '__explicit_bzero_constn' optimization that uses VLA, which is
not portable and source of issues in a lot of projects (llvmlinux for instance),
I did not see much traction on 'Compiler support for erasure of sensitive data'
thread for adding a similar feature at compiler side. 

Also, as pointed out by Szabolcs Nagy, this 'best effort' contains a set of
limitations:

* async signal handler copying all the register state on sigaltstack
* internal counters and debug features making sensitive info observable
* timing/cache-effect side channels that let other processes get info
* compiling to a highlevel language (js) with different kind of leaks
* running under emulator/debugger that can make secrets visible

So I am not sure if this is a good idea do add this symbol on glibc, something
it will require to carry on indefinitely and that might be replaced either
by some compiler directive or by more correct solutions (hardware assistant).
Also this can be enabled project by project in a very easy way if it decides
that is worth to implement. 

On 15-09-2015 11:21, Zack Weinberg wrote:
> Ping.
> 
> On Wed, Sep 9, 2015 at 11:31 AM, Zack Weinberg <zackw@panix.com> wrote:
>> This updated patchset adds to the manual discussion of the situation
>> where using explicit_bzero *creates* a copy of sensitive data in memory,
>> which would not otherwise have been created.  There are no changes to
>> the code.  Earlier discussion with Florian and Adhemerval explored some
>> possible alternative implementation strategies but reached the
>> conclusion that this really is the best we can do without compiler support.
>>
>> zw
  
Zack Weinberg Sept. 15, 2015, 3:36 p.m. UTC | #3
On Tue, Sep 15, 2015 at 10:49 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> At first I was convinced that adding this symbol would be a good approach,
> but after reading comments from Rick Felker and Szabolcs Nagy I am not sure
> any more.

I understand where you are coming from, but I must insist that the
perfect not be allowed to be the enemy of the good.

There is clear demand from application programmers for this API.  It
is not a perfect API, but having it in libc is strictly better than
having each application reinvent it, because: if applications have to
reinvent it, they may get it wrong; libc is the right place to
consolidate knowledge about what compiler support is or is not
available; and only libc can supply _FORTIFY_SOURCE wrappers.

Moreover, if a better approach (with compiler support) ever does
materialize, a libc-provided explicit_bzero can transparently morph
into an invocation of that better approach.  If it is left to
applications, each application would have to change to activate the
better approach.

> Besides the '__explicit_bzero_constn' optimization that uses VLA, which is
> not portable and source of issues in a lot of projects (llvmlinux for instance),

It is properly limited to C+actual gcc.  If this really is the
deciding factor, I am prepared to remove the optimization altogether,
but again, I do not see why the lack of _ideal_ compiler support for
this should mean that we shouldn't do the best we can with what we
have.

> I did not see much traction on 'Compiler support for erasure of sensitive data'
> thread for adding a similar feature at compiler side.

This is, sadly, true, but in my opinion it only strengthens the case
for the implementation in libc, because it means we may be waiting a
very long time for the compilers to step up.

> * async signal handler copying all the register state on sigaltstack
> * internal counters and debug features making sensitive info observable
> * timing/cache-effect side channels that let other processes get info
> * compiling to a highlevel language (js) with different kind of leaks
> * running under emulator/debugger that can make secrets visible

These vulnerabilities exist regardless of whether the C library
provides explicit_bzero; the inability to close _all_ the holes right
now should not stop us from closing a hole we _can_ close right now.

> So I am not sure if this is a good idea do add this symbol on glibc, something
> it will require to carry on indefinitely and that might be replaced either
> by some compiler directive or by more correct solutions (hardware assistant).

The backward compatibility load is trivial: two exported symbols, of
which one is an alias for a symbol that already exists, and the other
is a thunk compiling to five instructions or less.  By way of
comparison, the backward compatibility symbols for <regexp.h> are ~150
bytes of code and ~12 bytes of bss.

> Also this can be enabled project by project in a very easy way if it decides
> that is worth to implement.

This has already happened.  codesearch.debian.net reports 597 mentions
of explicit_bzero, 645 mentions of OPENSSL_cleanse, 6 mentions of
explicit_memset, 721 mentions of memset_s, 328 mentions of
memzero_explicit, 216 mentions of memwipe, 295 mentions of wipememory.
We wouldn't be having this conversation at all if there weren't a
demonstrated demand from the application side.

zw
  
Adhemerval Zanella Netto Sept. 15, 2015, 4:08 p.m. UTC | #4
On 15-09-2015 12:36, Zack Weinberg wrote:
> On Tue, Sep 15, 2015 at 10:49 AM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> At first I was convinced that adding this symbol would be a good approach,
>> but after reading comments from Rick Felker and Szabolcs Nagy I am not sure
>> any more.
> 
> I understand where you are coming from, but I must insist that the
> perfect not be allowed to be the enemy of the good.
> 
> There is clear demand from application programmers for this API.  It
> is not a perfect API, but having it in libc is strictly better than
> having each application reinvent it, because: if applications have to
> reinvent it, they may get it wrong; libc is the right place to
> consolidate knowledge about what compiler support is or is not
> available; and only libc can supply _FORTIFY_SOURCE wrappers.
> 
> Moreover, if a better approach (with compiler support) ever does
> materialize, a libc-provided explicit_bzero can transparently morph
> into an invocation of that better approach.  If it is left to
> applications, each application would have to change to activate the
> better approach.

It boils down to the same argument to add the str{l}cpy and families that
now and then arises in libc-alpha: applications programmers usage is only
one factor (and imho not even the priority one) on GLIBC API design and
extension.

And also based on same discussion, last time the person trying to convince
us this would a good API to include could not really show any compelling
reason do so.

> 
>> Besides the '__explicit_bzero_constn' optimization that uses VLA, which is
>> not portable and source of issues in a lot of projects (llvmlinux for instance),
> 
> It is properly limited to C+actual gcc.  If this really is the
> deciding factor, I am prepared to remove the optimization altogether,
> but again, I do not see why the lack of _ideal_ compiler support for
> this should mean that we shouldn't do the best we can with what we
> have.

That is not really the issue, but Rich indeed remind us it is using VLA and 
although you profiling analysis showed us gain in code geration, for *strict*
portability I do no see it the best approach (also, glibc code does not use
VLA in any other place afaik).

> 
>> I did not see much traction on 'Compiler support for erasure of sensitive data'
>> thread for adding a similar feature at compiler side.
> 
> This is, sadly, true, but in my opinion it only strengthens the case
> for the implementation in libc, because it means we may be waiting a
> very long time for the compilers to step up.
> 
>> * async signal handler copying all the register state on sigaltstack
>> * internal counters and debug features making sensitive info observable
>> * timing/cache-effect side channels that let other processes get info
>> * compiling to a highlevel language (js) with different kind of leaks
>> * running under emulator/debugger that can make secrets visible
> 
> These vulnerabilities exist regardless of whether the C library
> provides explicit_bzero; the inability to close _all_ the holes right
> now should not stop us from closing a hole we _can_ close right now.
> 
>> So I am not sure if this is a good idea do add this symbol on glibc, something
>> it will require to carry on indefinitely and that might be replaced either
>> by some compiler directive or by more correct solutions (hardware assistant).
> 
> The backward compatibility load is trivial: two exported symbols, of
> which one is an alias for a symbol that already exists, and the other
> is a thunk compiling to five instructions or less.  By way of
> comparison, the backward compatibility symbols for <regexp.h> are ~150
> bytes of code and ~12 bytes of bss.

I agree with you, but my view is if it is worth to add on *GLIBC* a functionality
that has very limited usage and a lot of limitations.  

> 
>> Also this can be enabled project by project in a very easy way if it decides
>> that is worth to implement.
> 
> This has already happened.  codesearch.debian.net reports 597 mentions
> of explicit_bzero, 645 mentions of OPENSSL_cleanse, 6 mentions of
> explicit_memset, 721 mentions of memset_s, 328 mentions of
> memzero_explicit, 216 mentions of memwipe, 295 mentions of wipememory.
> We wouldn't be having this conversation at all if there weren't a
> demonstrated demand from the application side.

And as for str{l}cpy it does not really mean they are using the better
approach to fix its issues it is proposing to fix. Or even, if using
the API is indeed implement the security fixes they are aiming for.

I would like to hear more comments from other GLIBC maintainers for the
inclusion of the API.

> 
> zw
>
  
Zack Weinberg Sept. 15, 2015, 4:30 p.m. UTC | #5
On Tue, Sep 15, 2015 at 12:08 PM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> On 15-09-2015 12:36, Zack Weinberg wrote:
>> There is clear demand from application programmers for this API.  It
>> is not a perfect API, but having it in libc is strictly better than
>> having each application reinvent it, because: [...]
>
> It boils down to the same argument to add the str{l}cpy and families that
> now and then arises in libc-alpha: applications programmers usage is only
> one factor (and imho not even the priority one) on GLIBC API design and
> extension.

To be honest, I believe strlcpy et al *should* be added to glibc,
because I believe the existence of a non-deprecated function in at
least two BSD C libraries should be taken as sufficient reason *all by
itself* to add it to glibc.

However, the case for strlcpy is much weaker than the case for
explicit_bzero.  The argument against strlcpy, as I understand it, is
that it does not solve *the problem it was designed to solve*.  The
strongest argument against explicit_bzero, by contrast, is that it
does not solve *a generalization of the problem it was designed to
solve*.

Thus, the argument against strlcpy is an argument on the merits of the
function itself, whereas the argument against explicit_bzero falls
under making the perfect the enemy of the good.

> And also based on same discussion, last time the person trying to convince
> us this would a good API to include could not really show any compelling
> reason do so. ... my view is if it is worth to add on *GLIBC* a functionality
> that has very limited usage and a lot of limitations.

It is true that it is used only under special circumstances, but these
special circumstances are common enough that the functionality exists
(under some name) in all of the BSDs, OSX, Windows, the Linux kernel,
OpenSSL, and libgcrypt. Moreover there are places *within glibc
itself* (specifically, crypt/) that *ought* to be using it.  If that
is not sufficiently compelling reason to add something, what *would*
you consider compelling?

> And as for str{l}cpy it does not really mean they are using the better
> approach to fix its issues it is proposing to fix. Or even, if using
> the API is indeed implement the security fixes they are aiming for.

Unlike strlcpy, the "ideal" data sanitization behavior would be a
*superset* of what explicit_bzero does.  Therefore explicit_bzero is
at least a step in the right direction.

> That is not really the issue, but Rich indeed remind us it is using VLA and
> although you profiling analysis showed us gain in code geration, for *strict*
> portability I do no see it the best approach (also, glibc code does not use
> VLA in any other place afaik).

I really don't think bits/string2.h is the place to quibble about
portability, but again, I will take the damn optimization out if it is
a deal-breaker.  I wasn't expecting to have nearly as much of an
argument about that bit.

> I would like to hear more comments from other GLIBC maintainers for the
> inclusion of the API.

I also.

zw
  
Segher Boessenkool Sept. 15, 2015, 6:49 p.m. UTC | #6
On Tue, Sep 15, 2015 at 01:08:44PM -0300, Adhemerval Zanella wrote:
> >> Also this can be enabled project by project in a very easy way if it decides
> >> that is worth to implement.
> > 
> > This has already happened.  codesearch.debian.net reports 597 mentions
> > of explicit_bzero, 645 mentions of OPENSSL_cleanse, 6 mentions of
> > explicit_memset, 721 mentions of memset_s, 328 mentions of
> > memzero_explicit, 216 mentions of memwipe, 295 mentions of wipememory.
> > We wouldn't be having this conversation at all if there weren't a
> > demonstrated demand from the application side.
> 
> And as for str{l}cpy it does not really mean they are using the better
> approach to fix its issues it is proposing to fix. Or even, if using
> the API is indeed implement the security fixes they are aiming for.

Neither explicit_bzero in glibc nor something similar in GCC can ever
produce this hoped-for security: there always will remain cases where
data escapes.  But it is good for defense-in-depth, as long as the
documentation makes it very clear that there are no promises that every
trace of the secret data will be gone.  Although of course many people
will just ignore such warnings and use this as snake oil, as faerie dust
that you sprinkle over your code.


Segher
  

Patch

[NEWS:]
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.

[ChangeLog:]
	* 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/string2.h: Optimize explicit_bzero when possible.
	* string/bits/string3.h: Fortify explicit_bzero. Remove stray
        blank lines.
	* 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/aarch64/bzero.S
	* sysdeps/alpha/bzero.S
	* sysdeps/i386/bzero.c
	* 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, convert to prototyped function definition and
	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 GLIBC_2.23 stanza containing explicit_bzero and
	__explicit_bzero_chk.
---
 debug/Makefile                                     |   1 +
 debug/Versions                                     |   3 +
 debug/explicit_bzero_chk.c                         |  28 ++++++
 debug/memset_chk.c                                 |   8 +-
 debug/tst-chk1.c                                   |  89 ++++++++++++++++++
 include/string.h                                   |   4 +
 manual/string.texi                                 | 101 +++++++++++++++++++++
 string/Makefile                                    |   3 +-
 string/Versions                                    |   3 +
 string/bits/string2.h                              |  28 ++++++
 string/bits/string3.h                              |  43 ++++++++-
 string/bzero.c                                     |   1 +
 string/string.h                                    |   4 +
 string/test-explicit_bzero.c                       |  21 +++++
 string/test-memset.c                               |  10 +-
 sysdeps/aarch64/bzero.S                            |   1 +
 sysdeps/alpha/bzero.S                              |   1 +
 sysdeps/arm/nacl/libc.abilist                      |   4 +
 sysdeps/i386/bzero.c                               |   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/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       |   4 +
 sysdeps/unix/sysv/linux/alpha/libc.abilist         |   4 +
 sysdeps/unix/sysv/linux/arm/libc.abilist           |   4 +
 sysdeps/unix/sysv/linux/hppa/libc.abilist          |   4 +
 sysdeps/unix/sysv/linux/i386/libc.abilist          |   4 +
 sysdeps/unix/sysv/linux/ia64/libc.abilist          |   4 +
 sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist |   4 +
 sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist   |   4 +
 sysdeps/unix/sysv/linux/microblaze/libc.abilist    |   4 +
 .../unix/sysv/linux/mips/mips32/fpu/libc.abilist   |   4 +
 .../unix/sysv/linux/mips/mips32/nofpu/libc.abilist |   4 +
 .../unix/sysv/linux/mips/mips64/n32/libc.abilist   |   4 +
 .../unix/sysv/linux/mips/mips64/n64/libc.abilist   |   4 +
 sysdeps/unix/sysv/linux/nios2/libc.abilist         |   4 +
 .../sysv/linux/powerpc/powerpc32/fpu/libc.abilist  |   4 +
 .../linux/powerpc/powerpc32/nofpu/libc.abilist     |   4 +
 .../sysv/linux/powerpc/powerpc64/libc-le.abilist   |   4 +
 .../unix/sysv/linux/powerpc/powerpc64/libc.abilist |   4 +
 sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist  |   4 +
 sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist  |   4 +
 sysdeps/unix/sysv/linux/sh/libc.abilist            |   4 +
 sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist |   4 +
 sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist |   4 +
 .../sysv/linux/tile/tilegx/tilegx32/libc.abilist   |   4 +
 .../sysv/linux/tile/tilegx/tilegx64/libc.abilist   |   4 +
 sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist  |   4 +
 sysdeps/unix/sysv/linux/x86_64/64/libc.abilist     |   4 +
 sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist    |   4 +
 sysdeps/x86_64/memset.S                            |   2 +
 sysdeps/x86_64/multiarch/memset.S                  |   2 +-
 68 files changed, 479 insertions(+), 17 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 9ff357b..93e044f 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..15330c6
--- /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 for plain bzero, because
+   bits/string3.h cannot always optimize explicit_bzero to memset.
+   See comments there, and "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 293172f..4df7c45 100644
--- a/debug/memset_chk.c
+++ b/debug/memset_chk.c
@@ -16,17 +16,13 @@ 
    <http://www.gnu.org/licenses/>.  */
 
 #include <string.h>
-#include <memcopy.h>
 
 void *
-__memset_chk (dstpp, c, len, dstlen)
-     void *dstpp;
-     int c;
-     size_t len;
-     size_t dstlen;
+__memset_chk (void *dstpp, int c, size_t len, size_t dstlen)
 {
   if (__glibc_unlikely (dstlen < len))
     __chk_fail ();
 
   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 c57671e..3d0f7ca 100644
--- a/include/string.h
+++ b/include/string.h
@@ -160,6 +160,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 8424a61..8246c10 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/string2.h b/string/bits/string2.h
index 7645176..a1efbe3 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -194,6 +194,34 @@  __STRING2_COPY_TYPE (8);
 #  define __bzero(s, n) __builtin_memset (s, '\0', n)
 # 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
 
 
diff --git a/string/bits/string3.h b/string/bits/string3.h
index 4d11aa6..c6b38d4 100644
--- a/string/bits/string3.h
+++ b/string/bits/string3.h
@@ -42,10 +42,10 @@  __warndecl (__warn_memset_zero_len,
 # ifdef __USE_MISC
 #  undef bcopy
 #  undef bzero
+#  undef explicit_bzero
 # endif
 #endif
 
-
 __fortify_function void *
 __NTH (memcpy (void *__restrict __dest, const void *__restrict __src,
 	       size_t __len))
@@ -68,7 +68,6 @@  __NTH (mempcpy (void *__restrict __dest, const void *__restrict __src,
 }
 #endif
 
-
 /* The first two tests here help to catch a somewhat common problem
    where the second and third parameter are transposed.  This is
    especially problematic if the intended fill value is zero.  In this
@@ -102,6 +101,43 @@  __NTH (bzero (void *__dest, size_t __len))
 {
   (void) __builtin___memset_chk (__dest, '\0', __len, __bos0 (__dest));
 }
+
+/* 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,
+                            (void *__dest, size_t __len),
+                            explicit_bzero);
+
+__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));
+  else
+    __explicit_bzero_alias (__dest, __len);
+}
 #endif
 
 __fortify_function char *
@@ -118,7 +154,6 @@  __NTH (stpcpy (char *__restrict __dest, const char *__restrict __src))
 }
 #endif
 
-
 __fortify_function char *
 __NTH (strncpy (char *__restrict __dest, const char *__restrict __src,
 		size_t __len))
@@ -141,14 +176,12 @@  __NTH (stpncpy (char *__dest, const char *__src, size_t __n))
   return __stpncpy_alias (__dest, __src, __n);
 }
 
-
 __fortify_function char *
 __NTH (strcat (char *__restrict __dest, const char *__restrict __src))
 {
   return __builtin___strcat_chk (__dest, __src, __bos (__dest));
 }
 
-
 __fortify_function char *
 __NTH (strncat (char *__restrict __dest, const char *__restrict __src,
 		size_t __len))
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 9f3af46..ca56857 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
 # define TEST_NAME "memset"
 #endif
@@ -35,7 +39,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/aarch64/bzero.S b/sysdeps/aarch64/bzero.S
index 7343896..375457b 100644
--- a/sysdeps/aarch64/bzero.S
+++ b/sysdeps/aarch64/bzero.S
@@ -25,3 +25,4 @@  ENTRY(__bzero)
 	b	__memset
 END(__bzero)
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
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 bef1259..f0c6a36 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1835,3 +1835,7 @@  GLIBC_2.22
  write F
  writev F
  wscanf F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
diff --git a/sysdeps/i386/bzero.c b/sysdeps/i386/bzero.c
index 1a89444..c7575f8 100644
--- a/sysdeps/i386/bzero.c
+++ b/sysdeps/i386/bzero.c
@@ -76,6 +76,7 @@  __bzero (dstpp, len)
 		"memory");
 }
 weak_alias (__bzero, bzero)
+weak_alias (__bzero, explicit_bzero)
 
 #else
 #include <string/bzero.c>
diff --git a/sysdeps/i386/i586/bzero.S b/sysdeps/i386/i586/bzero.S
index 84d2f70..23ee2c9 100644
--- a/sysdeps/i386/i586/bzero.S
+++ b/sysdeps/i386/i586/bzero.S
@@ -1,3 +1,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 bc26501..c15e4a7 100644
--- a/sysdeps/i386/i586/memset.S
+++ b/sysdeps/i386/i586/memset.S
@@ -119,3 +119,4 @@  L(2):	shrl	$2, %ecx	/* convert byte count to longword count */
 #endif
 END (memset)
 libc_hidden_builtin_def (memset)
+libc_hidden_builtin_def (__memset_chk)
diff --git a/sysdeps/i386/i686/bzero.S b/sysdeps/i386/i686/bzero.S
index 34b0faa..25a9811 100644
--- a/sysdeps/i386/i686/bzero.S
+++ b/sysdeps/i386/i686/bzero.S
@@ -1,3 +1,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 b6dbf2a..01b79c0 100644
--- a/sysdeps/i386/i686/memset.S
+++ b/sysdeps/i386/i686/memset.S
@@ -98,6 +98,7 @@  ENTRY (memset)
 #endif
 END (memset)
 libc_hidden_builtin_def (memset)
+libc_hidden_builtin_def (__memset_chk)
 
 #if defined PIC && IS_IN (libc) && !BZERO_P
 strong_alias (__memset_chk, __memset_zero_constant_len_parameter)
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/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 3e0f329..c2b077f 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2084,3 +2084,7 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 58c8b32..dd75663 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -1825,6 +1825,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.2
  GLIBC_2.2 A
  _IO_adjust_wcolumn F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index f2b20ad..6014129 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -92,6 +92,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index cf0ad90..a563c40 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -98,6 +98,10 @@  GLIBC_2.19
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.2
  GLIBC_2.2 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index fcf1b72..5c4972f 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2026,6 +2026,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 16c2e3d..16c82e9 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1884,6 +1884,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 902b0c3..945dc34 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -93,6 +93,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.4
  GLIBC_2.4 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 4db00b0..fd50ed5 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1982,6 +1982,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index f1f76a1..8c3b4aa 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2083,3 +2083,7 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ 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 2d51989..2cf852c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1954,6 +1954,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 b012bdf..86c2f78 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1952,6 +1952,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 9db0e8b..8f6890d 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1950,6 +1950,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 eecfcfe..d1975c7 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1944,6 +1944,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index b10bf62..0bc6c5c 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2124,3 +2124,7 @@  GLIBC_2.21
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ 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 0f15463..e80f798 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1986,6 +1986,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 7bcaa07..bcc8383 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1992,6 +1992,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 c0b3985..c66effb 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2172,3 +2172,7 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index e58a00d..2dc2424 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -93,6 +93,10 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  _Exit F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 0ce7824..eaca001 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1987,6 +1987,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 dc79912..7513fda 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1883,6 +1883,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 9ed1b45..c5625b6 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1867,6 +1867,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 5a40ff3..ea7aa50 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1978,6 +1978,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index fa70645..0da655f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1911,6 +1911,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 dd215d7..f968929 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2094,3 +2094,7 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ 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 ef4747a..4305450 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2094,3 +2094,7 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index dd215d7..f968929 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2094,3 +2094,7 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ 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 b377b04..fd7c07e 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1857,6 +1857,10 @@  GLIBC_2.2.6
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
 GLIBC_2.3
  GLIBC_2.3 A
  __ctype_b_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 5f70329..c632178 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2092,3 +2092,7 @@  GLIBC_2.18
 GLIBC_2.22
  GLIBC_2.22 A
  fmemopen F
+GLIBC_2.23
+ GLIBC_2.23 A
+ __explicit_bzero_chk F
+ explicit_bzero F
diff --git a/sysdeps/x86_64/memset.S b/sysdeps/x86_64/memset.S
index e496254..7f1e136 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 16fefa7..03e62e5 100644
--- a/sysdeps/x86_64/multiarch/memset.S
+++ b/sysdeps/x86_64/multiarch/memset.S
@@ -48,7 +48,7 @@  END(memset)
    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
+	.globl __GI_##name; __GI_##name = name
 #  endif
 
 #  undef strong_alias
-- 
2.5.1