[2/4] New string function explicit_bzero (from OpenBSD).

Message ID 9d17da53214c24a908092519d98bb93f4e6429f1.1471452664.git.zackw@panix.com
State Superseded
Headers

Commit Message

Zack Weinberg Aug. 17, 2016, 5:19 p.m. UTC
  explicit_bzero(s, n) is the same as memset(s, 0, n), except that the
compiler is not allowed to delete a call to explicit_bzero even if the
memory pointed to by 's' is dead after the call.  We achieve this effect
by defining it to call memset() and then a second function,

    extern void __glibc_read_memory (const void *, size_t)
       __attribute_noinline__;

which does nothing -- but the compiler is prevented from knowing that
it does nothing, and so the pointer "escapes" and the memory is not
treated as dead.  (Concretely, __glibc_read_memory is forced
out-of-line, defined in a file containing nothing else, and comments
in both string/read_memory.c and string/Makefile document that it must
not be subject to link-time optimization.)

	* string/explicit_bzero.c, string/read_memory.c: New routines.
	* string/test-explicit_bzero.c: New test.
	* string/Makefile (routines, strop-tests): Add them.
	* string/test-memset.c: Add ifdeffage for testing explicit_bzero.
	* string/string.h [__USE_MISC]: Declare explicit_bzero and
	__glibc_read_memory.
	* string/bits/string2.h [__USE_MISC]: Provide inline version of
	explicit_bzero.

	* manual/string.texi: Document explicit_bzero.

	* string/Versions [GLIBC_2.25]: Add explicit_bzero and
	__glibc_read_memory.

	* include/string.h: Hidden prototype for __internal_glibc_read_memory.
	* sysdeps/arm/nacl/libc.abilist
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist
	* sysdeps/unix/sysv/linux/alpha/libc.abilist
	* sysdeps/unix/sysv/linux/arm/libc.abilist
	* sysdeps/unix/sysv/linux/hppa/libc.abilist
	* sysdeps/unix/sysv/linux/i386/libc.abilist
	* sysdeps/unix/sysv/linux/ia64/libc.abilist
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
	* sysdeps/unix/sysv/linux/nios2/libc.abilist
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
	* sysdeps/unix/sysv/linux/sh/libc.abilist
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
	* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist:
	Add entries for explicit_bzero and __glibc_read_memory.
---
 include/string.h                                   |   2 +
 manual/string.texi                                 | 101 +++++++++++++++++++++
 string/Makefile                                    |  10 +-
 string/Versions                                    |   7 ++
 string/bits/string2.h                              |  14 ++-
 string/explicit_bzero.c                            |  30 ++++++
 string/read_memory.c                               |  41 +++++++++
 string/string.h                                    |   9 ++
 string/test-explicit_bzero.c                       |  20 ++++
 string/test-memset.c                               |  10 +-
 sysdeps/arm/nacl/libc.abilist                      |   2 +
 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 +
 39 files changed, 298 insertions(+), 4 deletions(-)
 create mode 100644 string/explicit_bzero.c
 create mode 100644 string/read_memory.c
 create mode 100644 string/test-explicit_bzero.c
  

Comments

Florian Weimer Aug. 18, 2016, 6:31 p.m. UTC | #1
On 08/17/2016 07:19 PM, Zack Weinberg wrote:
> +#ifdef __USE_MISC
> +/* As bzero, but the compiler will not delete a call to this
> +   function, even if S is dead after the call.  Note: this function
> +   has its own implementation file and should not be slurped into
> +   string-inlines.o.  */
> +__extern_inline void
> +explicit_bzero (void *__s, size_t __n)
> +{
> +  memset (__s, '\0', __n);
> +  __glibc_read_memory (__s, __n);
> +}
> +#endif

__extern_inline can expand to nothing at all, and you would get multiple 
definitions of explicit_bzero this way.

I don't think we want explicit_bzero to be inlined, it's useful to have 
this name in the executable.  Furthermore, we might want to add 
additional state clearing later, so an implementation in libc.so.6 seems 
desirable anyway.

For an implementation in libc, there is currently no different between 
the __glibc_read_memory kludge and a full memory barrier, so I suggest 
to go with the latter.  (The explicit_bzero call will serve as a rather 
broad barrier anyway, but we can annotate it with __THROW.)

Thanks,
Florian
  
Torvald Riegel Aug. 18, 2016, 8:53 p.m. UTC | #2
On Thu, 2016-08-18 at 20:31 +0200, Florian Weimer wrote:
> On 08/17/2016 07:19 PM, Zack Weinberg wrote:
> > +#ifdef __USE_MISC
> > +/* As bzero, but the compiler will not delete a call to this
> > +   function, even if S is dead after the call.  Note: this function
> > +   has its own implementation file and should not be slurped into
> > +   string-inlines.o.  */
> > +__extern_inline void
> > +explicit_bzero (void *__s, size_t __n)
> > +{
> > +  memset (__s, '\0', __n);
> > +  __glibc_read_memory (__s, __n);
> > +}
> > +#endif
> 
> __extern_inline can expand to nothing at all, and you would get multiple 
> definitions of explicit_bzero this way.
> 
> I don't think we want explicit_bzero to be inlined, it's useful to have 
> this name in the executable.  Furthermore, we might want to add 
> additional state clearing later, so an implementation in libc.so.6 seems 
> desirable anyway.
> 
> For an implementation in libc, there is currently no different between 
> the __glibc_read_memory kludge and a full memory barrier, so I suggest 
> to go with the latter.  (The explicit_bzero call will serve as a rather 
> broad barrier anyway, but we can annotate it with __THROW.)

I suppose we just want a compiler barrier here though, and don't need a
memory barrier in the sense of something that constrains HW reordering.
  
Adhemerval Zanella Netto Aug. 19, 2016, 12:43 p.m. UTC | #3
On 18/08/2016 17:53, Torvald Riegel wrote:
> On Thu, 2016-08-18 at 20:31 +0200, Florian Weimer wrote:
>> On 08/17/2016 07:19 PM, Zack Weinberg wrote:
>>> +#ifdef __USE_MISC
>>> +/* As bzero, but the compiler will not delete a call to this
>>> +   function, even if S is dead after the call.  Note: this function
>>> +   has its own implementation file and should not be slurped into
>>> +   string-inlines.o.  */
>>> +__extern_inline void
>>> +explicit_bzero (void *__s, size_t __n)
>>> +{
>>> +  memset (__s, '\0', __n);
>>> +  __glibc_read_memory (__s, __n);
>>> +}
>>> +#endif
>>
>> __extern_inline can expand to nothing at all, and you would get multiple 
>> definitions of explicit_bzero this way.
>>
>> I don't think we want explicit_bzero to be inlined, it's useful to have 
>> this name in the executable.  Furthermore, we might want to add 
>> additional state clearing later, so an implementation in libc.so.6 seems 
>> desirable anyway.
>>
>> For an implementation in libc, there is currently no different between 
>> the __glibc_read_memory kludge and a full memory barrier, so I suggest 
>> to go with the latter.  (The explicit_bzero call will serve as a rather 
>> broad barrier anyway, but we can annotate it with __THROW.)
> 
> I suppose we just want a compiler barrier here though, and don't need a
> memory barrier in the sense of something that constrains HW reordering.

I would also suggest to avoid adding this inline optimization, it just add
another exported symbol by glibc with little performance benefit.
  
Florian Weimer Aug. 19, 2016, 12:50 p.m. UTC | #4
On 08/18/2016 10:53 PM, Torvald Riegel wrote:
> On Thu, 2016-08-18 at 20:31 +0200, Florian Weimer wrote:
>> I don't think we want explicit_bzero to be inlined, it's useful to have
>> this name in the executable.  Furthermore, we might want to add
>> additional state clearing later, so an implementation in libc.so.6 seems
>> desirable anyway.
>>
>> For an implementation in libc, there is currently no different between
>> the __glibc_read_memory kludge and a full memory barrier, so I suggest
>> to go with the latter.  (The explicit_bzero call will serve as a rather
>> broad barrier anyway, but we can annotate it with __THROW.)
>
> I suppose we just want a compiler barrier here though, and don't need a
> memory barrier in the sense of something that constrains HW reordering.

Yes, I meant an asm statement with a "memory" clobber.

Thanks,
Florian
  
Zack Weinberg Aug. 19, 2016, 1 p.m. UTC | #5
On 08/19/2016 08:43 AM, Adhemerval Zanella wrote:
> On 18/08/2016 17:53, Torvald Riegel wrote:
>> On Thu, 2016-08-18 at 20:31 +0200, Florian Weimer wrote:
>>> On 08/17/2016 07:19 PM, Zack Weinberg wrote:
>>>> +#ifdef __USE_MISC
>>>> +/* As bzero, but the compiler will not delete a call to this
>>>> +   function, even if S is dead after the call.  Note: this function
>>>> +   has its own implementation file and should not be slurped into
>>>> +   string-inlines.o.  */
>>>> +__extern_inline void
>>>> +explicit_bzero (void *__s, size_t __n)
>>>> +{
>>>> +  memset (__s, '\0', __n);
>>>> +  __glibc_read_memory (__s, __n);
>>>> +}
>>>> +#endif
>>>
>>> __extern_inline can expand to nothing at all, and you would get multiple 
>>> definitions of explicit_bzero this way.

OK, what should I be using instead?

>>> I don't think we want explicit_bzero to be inlined, it's useful to have 
>>> this name in the executable.  Furthermore, we might want to add 
>>> additional state clearing later, so an implementation in libc.so.6 seems 
>>> desirable anyway.

Oddly enough, inlining the memset leads to better security properties
for generated code.  Remember the "key that lives in the vector
registers until it has to be copied onto the stack to be erased" scenario?

---
#include <emmintrin.h>
#include <string.h>

extern void explicit_bzero (void *ptr, size_t size);

extern __m128 get_key ();
extern void encrypt_with_key (__m128 key, void *data, size_t size);

void encrypt (void *data, size_t size)
{
  __m128 key = get_key ();
  encrypt_with_key (key, data, size);
  explicit_bzero (&key, sizeof key);
}
---

(Assume an ABI where __m128 actually gets passed in registers.)

If you expose the memset to inlining,  the key *won't* be copied into
the stack and then immediately erased; the compiler will just dutifully
clear 16 bytes of the stack and then pass them to __glibc_read_memory.
It still won't be erased from the vector registers, but that can only be
fixed with compiler support.

(It also leads to significantly more compact code -- see my experiment
with OpenSSL from last year -- but that's not as important.)

>> I suppose we just want a compiler barrier here though, and don't need a
>> memory barrier in the sense of something that constrains HW reordering.

That is correct; however, the "memory barrier" I was talking about was

    asm volatile ("" ::: "memory");

which is also only a compiler barrier.

> I would also suggest to avoid adding this inline optimization, it just add
> another exported symbol by glibc with little performance benefit. 

The *other* reason why I want to keep the inline optimization is that it
means I don't need to add __explicit_bzero_chk (which, because of
ifuncs, means futzing with *every sysdeps definition of memset*!).  So
either way there's going to be a new exported symbol.

zw
  
Adhemerval Zanella Netto Aug. 19, 2016, 2 p.m. UTC | #6
On 19/08/2016 10:00, Zack Weinberg wrote:
> On 08/19/2016 08:43 AM, Adhemerval Zanella wrote:
>> On 18/08/2016 17:53, Torvald Riegel wrote:
>>> On Thu, 2016-08-18 at 20:31 +0200, Florian Weimer wrote:
>>>> On 08/17/2016 07:19 PM, Zack Weinberg wrote:
>>>>> +#ifdef __USE_MISC
>>>>> +/* As bzero, but the compiler will not delete a call to this
>>>>> +   function, even if S is dead after the call.  Note: this function
>>>>> +   has its own implementation file and should not be slurped into
>>>>> +   string-inlines.o.  */
>>>>> +__extern_inline void
>>>>> +explicit_bzero (void *__s, size_t __n)
>>>>> +{
>>>>> +  memset (__s, '\0', __n);
>>>>> +  __glibc_read_memory (__s, __n);
>>>>> +}
>>>>> +#endif
>>>>
>>>> __extern_inline can expand to nothing at all, and you would get multiple 
>>>> definitions of explicit_bzero this way.
> 
> OK, what should I be using instead?

Fortify functions uses '__fortify_function' which defines both 
__extern_always_inline and __attribute_artificial__.  However fortify is guarded
by _FORTIFY_SOURCE, which requires GCC 4.1 (so __extern_always_inline will be
defined anyway).

Stdio also defines:

#ifndef __extern_inline
# define __STDIO_INLINE inline
#else
# define __STDIO_INLINE __extern_inline
#endif


#ifdef __USE_EXTERN_INLINES
...
#endif

But I think this will also only add unnecessary complexity on the patch.

Also, another issue with gnu_inline is when building for C++ it might get also
multiple definitions [1].

That's why I think simpler solution would be just to remove this inline
optimization.


[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=41194


> 
>>>> I don't think we want explicit_bzero to be inlined, it's useful to have 
>>>> this name in the executable.  Furthermore, we might want to add 
>>>> additional state clearing later, so an implementation in libc.so.6 seems 
>>>> desirable anyway.
> 
> Oddly enough, inlining the memset leads to better security properties
> for generated code.  Remember the "key that lives in the vector
> registers until it has to be copied onto the stack to be erased" scenario?
> 
> ---
> #include <emmintrin.h>
> #include <string.h>
> 
> extern void explicit_bzero (void *ptr, size_t size);
> 
> extern __m128 get_key ();
> extern void encrypt_with_key (__m128 key, void *data, size_t size);
> 
> void encrypt (void *data, size_t size)
> {
>   __m128 key = get_key ();
>   encrypt_with_key (key, data, size);
>   explicit_bzero (&key, sizeof key);
> }
> ---
> 
> (Assume an ABI where __m128 actually gets passed in registers.)
> 
> If you expose the memset to inlining,  the key *won't* be copied into
> the stack and then immediately erased; the compiler will just dutifully
> clear 16 bytes of the stack and then pass them to __glibc_read_memory.
> It still won't be erased from the vector registers, but that can only be
> fixed with compiler support.
> 
> (It also leads to significantly more compact code -- see my experiment
> with OpenSSL from last year -- but that's not as important.)

I also think compact code should not be a blocker here as well.  However I
do not have a better solution for this specific solution without compiler
support.

> 
>>> I suppose we just want a compiler barrier here though, and don't need a
>>> memory barrier in the sense of something that constrains HW reordering.
> 
> That is correct; however, the "memory barrier" I was talking about was
> 
>     asm volatile ("" ::: "memory");
> 
> which is also only a compiler barrier.
> 
>> I would also suggest to avoid adding this inline optimization, it just add
>> another exported symbol by glibc with little performance benefit. 
> 
> The *other* reason why I want to keep the inline optimization is that it
> means I don't need to add __explicit_bzero_chk (which, because of
> ifuncs, means futzing with *every sysdeps definition of memset*!).  So
> either way there's going to be a new exported symbol.
> 
> zw

I do not think this is really required, you can still add a default
debug/explicit_bzero_chk.c which will call explicit_bzero/memset.  Each
port already defines how internal memset is called (either using
internal ifunc or redirecting to a default symbol) so I see no need
to add arch specific implementations.

This does not prevent though to later we add arch-specific optimized
version (which might be ifunc).
  
Zack Weinberg Aug. 19, 2016, 4:06 p.m. UTC | #7
On Fri, Aug 19, 2016 at 10:00 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> On 19/08/2016 10:00, Zack Weinberg wrote:
>>
>> OK, what should I be using instead?
>
> [... some options which I will look into ...]
>
> That's why I think simpler solution would be just to remove this inline
> optimization.

It's really, really not simpler, though, because of the fortify issue...

>> The *other* reason why I want to keep the inline optimization is that it
>> means I don't need to add __explicit_bzero_chk (which, because of
>> ifuncs, means futzing with *every sysdeps definition of memset*!).  So
>> either way there's going to be a new exported symbol.
>
> I do not think this is really required, you can still add a default
> debug/explicit_bzero_chk.c which will call explicit_bzero/memset.

You missed the point; the point was that if we don't add
__glibc_read_memory then we have to add __explicit_bzero_chk, so
there's one new implementation-namespace exported symbol either way.

Anyway, it would be nice if that worked without modifying every
definition of memset, but it doesn't.  The problem is not that
__explicit_bzero_chk itself would need to be an ifunc (I agree that
that would be an unnecessary optimization); the problem is that
__explicit_bzero_chk would need to call __memset_chk from inside
libc.so.  There are currently no calls to __memset_chk inside libc.so,
which means there is no PLT bypass glue for __memset_chk.  And because
_some_ architectures define __memset_chk as an ifunc, it's in sysdeps,
and _every_ memset.S has to be audited and possibly touched.  This is
such a PITA that in
https://sourceware.org/ml/libc-alpha/2015-11/msg00467.html I appear to
have only done it for x86.

With the inline optimization, the fortified explicit_bzero can live
entirely within bits/string3.h and no modifications to __memset_chk
are required.

zw
  
Adhemerval Zanella Netto Aug. 19, 2016, 4:31 p.m. UTC | #8
On 19/08/2016 13:06, Zack Weinberg wrote:
> On Fri, Aug 19, 2016 at 10:00 AM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> On 19/08/2016 10:00, Zack Weinberg wrote:
>>>
>>> OK, what should I be using instead?
>>
>> [... some options which I will look into ...]
>>
>> That's why I think simpler solution would be just to remove this inline
>> optimization.
> 
> It's really, really not simpler, though, because of the fortify issue...
> 
>>> The *other* reason why I want to keep the inline optimization is that it
>>> means I don't need to add __explicit_bzero_chk (which, because of
>>> ifuncs, means futzing with *every sysdeps definition of memset*!).  So
>>> either way there's going to be a new exported symbol.
>>
>> I do not think this is really required, you can still add a default
>> debug/explicit_bzero_chk.c which will call explicit_bzero/memset.
> 
> You missed the point; the point was that if we don't add
> __glibc_read_memory then we have to add __explicit_bzero_chk, so
> there's one new implementation-namespace exported symbol either way.
> 
> Anyway, it would be nice if that worked without modifying every
> definition of memset, but it doesn't.  The problem is not that
> __explicit_bzero_chk itself would need to be an ifunc (I agree that
> that would be an unnecessary optimization); the problem is that
> __explicit_bzero_chk would need to call __memset_chk from inside
> libc.so.  There are currently no calls to __memset_chk inside libc.so,
> which means there is no PLT bypass glue for __memset_chk.  And because
> _some_ architectures define __memset_chk as an ifunc, it's in sysdeps,
> and _every_ memset.S has to be audited and possibly touched.  This is
> such a PITA that in
> https://sourceware.org/ml/libc-alpha/2015-11/msg00467.html I appear to
> have only done it for x86.
> 
> With the inline optimization, the fortified explicit_bzero can live
> entirely within bits/string3.h and no modifications to __memset_chk
> are required.

Well, current memset_chk default implementation just does:

  if (__glibc_unlikely (dstlen < len))             
    __chk_fail (); 

So it would be feasible imho to just this add and call memset instead
of memset_chk.

The problem, as pointed out by Florian, is not the symbol being exported
itself, but the inline definition where all the 'inline' definition might
either not being supported by the target compiler or have non-expected
side effects (as for C++ with -O0).  

The fortified version is mostly fine to use 'inline' definition because 
it is already guarded by _FORTIFY_SOURCE, but I think the default 
explicit_bzero guarded by __USE_MISC is not suffice.
  
Zack Weinberg Aug. 19, 2016, 7:54 p.m. UTC | #9
On Fri, Aug 19, 2016 at 12:31 PM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> Well, current memset_chk default implementation just does:
>
>   if (__glibc_unlikely (dstlen < len))
>     __chk_fail ();
>
> So it would be feasible imho to just this add and call memset instead
> of memset_chk.

For clarity, you are imagining this as the in-libc, out-of-line
implementation of __explicit_bzero_chk?  Because as long as there's
*some* inline definition of explicit_bzero, we have to have the
exported __glibc_read_memory and then I don't see why we shouldn't
have a string2.h non-fortified inline as well.

> The problem, as pointed out by Florian, is not the symbol being exported
> itself, but the inline definition where all the 'inline' definition might
> either not being supported by the target compiler or have non-expected
> side effects (as for C++ with -O0).

Did you miss that there *is* an out-of-line non-fortified
explicit_bzero?  Which means that the bug you pointed out should be a
non-issue.

zw
  
Adhemerval Zanella Netto Aug. 19, 2016, 9:15 p.m. UTC | #10
On 19/08/2016 16:54, Zack Weinberg wrote:
> On Fri, Aug 19, 2016 at 12:31 PM, Adhemerval Zanella
> <adhemerval.zanella@linaro.org> wrote:
>> Well, current memset_chk default implementation just does:
>>
>>   if (__glibc_unlikely (dstlen < len))
>>     __chk_fail ();
>>
>> So it would be feasible imho to just this add and call memset instead
>> of memset_chk.
> 
> For clarity, you are imagining this as the in-libc, out-of-line
> implementation of __explicit_bzero_chk?  Because as long as there's
> *some* inline definition of explicit_bzero, we have to have the
> exported __glibc_read_memory and then I don't see why we shouldn't
> have a string2.h non-fortified inline as well.

What I would like is, based on recent string inline headers cleanup,
is to avoid adding more implementation that in the future the compiler
can and would handle this transparently.  Ideally it would be better if
we just aims to clean all the optimization done in string2/string3 
headers (as we did for recent strspn, strbrk, etc. optimizations).

For this special case, I would advise go for the simple case: add a 
explicit_bzero and __explicit_bzero_chk in-libc as the other implementations.
However I do not have a strong opinion here.

> 
>> The problem, as pointed out by Florian, is not the symbol being exported
>> itself, but the inline definition where all the 'inline' definition might
>> either not being supported by the target compiler or have non-expected
>> side effects (as for C++ with -O0).
> 
> Did you miss that there *is* an out-of-line non-fortified
> explicit_bzero?  Which means that the bug you pointed out should be a
> non-issue.

The problem is not the existence of a out-of-line explicit_bzero, but
if __extern_inline would use or not the gnu_inline attribute.  With current
guards for inclusion of string2.h (OPTIMIZE and !__cplusplus) the only
case of a possible issue I can think of is if someone building with
GCC lower than 4.2 with an optimized build and -fno-inline (this will
define __extern_inline to just extern __inline and possible create
multiple definitions). My inclination is this should not be a blocker
though.
  

Patch

diff --git a/include/string.h b/include/string.h
index e145bfd..277c07d 100644
--- a/include/string.h
+++ b/include/string.h
@@ -99,6 +99,8 @@  libc_hidden_proto (memmem)
 extern __typeof (memmem) __memmem;
 libc_hidden_proto (__memmem)
 libc_hidden_proto (__ffs)
+extern __typeof (__glibc_read_memory) __internal_glibc_read_memory;
+libc_hidden_proto (__internal_glibc_read_memory)
 
 libc_hidden_builtin_proto (memchr)
 libc_hidden_builtin_proto (memcpy)
diff --git a/manual/string.texi b/manual/string.texi
index bce81a7..fe4ca48 100644
--- a/manual/string.texi
+++ b/manual/string.texi
@@ -34,6 +34,8 @@  too.
 * Search Functions::            Searching for a specific element or substring.
 * Finding Tokens in a String::  Splitting a string into tokens by looking
 				 for delimiters.
+* Erasing Sensitive Data::      Clearing memory which contains sensitive
+                                 data, after it's no longer needed.
 * strfry::                      Function for flash-cooking a string.
 * Trivial Encryption::          Obscuring data.
 * Encode Binary Data::          Encoding and Decoding of Binary Data.
@@ -2375,6 +2377,105 @@  contains no '/' bytes, then "." is returned.  The prototype for this
 function can be found in @file{libgen.h}.
 @end deftypefun
 
+@node Erasing Sensitive Data
+@section Erasing Sensitive Data
+
+It is sometimes necessary to make sure that a block of data in memory
+is erased after use, even if no correct C program could access it
+again.  For instance, a cryptographic key should not be allowed to
+survive on the stack after the program is finished using it, because
+there might be a bug that causes junk stack data, including the key,
+to be revealed to the outside world.  @code{memset} and @code{bzero}
+are not safe to use for this, because the C compiler knows what they
+do, and can delete ``unnecessary'' calls to them.  For this situation,
+@theglibc{} provides @code{explicit_bzero}, which is functionally
+identical to @code{bzero}, except that the C compiler will @emph{not}
+delete apparently-unnecessary calls.
+
+@comment string.h
+@comment BSD
+@deftypefun void explicit_bzero (void *@var{block}, size_t @var{len})
+@safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}}
+
+@code{explicit_bzero} writes zero into each of the first @var{len}
+bytes of the object beginning at @var{block}, just as @code{bzero}
+would.  The compiler will not delete a call to this function, even
+if the object beginning at @var{block} is never referred to again.
+
+@smallexample
+#include <string.h>
+
+extern void encrypt (const char *key, const char *in,
+                     char *out, size_t n);
+extern void genkey (const char *phrase, char *key);
+
+void encrypt_with_phrase (const char *phrase, const char *in,
+                          char *out, size_t n)
+@{
+  char key[16];
+  genkey (phrase, key);
+  encrypt (key, in, out, n);
+  explicit_bzero (key, 16);
+@}
+@end smallexample
+
+@noindent
+If @code{bzero} or @code{memset} had been used in this function, the C
+compiler might remove it as unnecessary, but it will not do this with
+@code{explicit_bzero}.
+
+@strong{Warning:} The @emph{only} optimization disabled by
+@code{explicit_bzero} is removal of ``unnecessary'' calls.  In all
+other respects, the compiler is allowed to optimize as it would for
+@code{memset}.  For instance, it may deduce that @var{block} cannot be
+a null pointer, and propagate this information both forward and
+backward in control flow.
+
+@strong{Warning:} The compiler is free to make additional copies of
+any object, or parts of it, in temporary storage areas (such as
+registers and ``scratch'' stack space).  @code{explicit_bzero} does
+not guarantee that temporary copies of sensitive data are destroyed.
+In fact, in some situations, using @code{explicit_bzero} will
+@emph{cause} creation of an additional copy, and only that copy will
+be cleared:
+
+@smallexample
+#include <string.h>
+
+struct key @{
+  unsigned long long low;
+  unsigned long long high;
+@};
+
+struct key get_key(void);
+void use_key(struct key);
+
+void
+with_clear(void)
+@{
+  struct key k;
+  k = get_key();
+  use_key(k);
+  explicit_bzero(&k, sizeof(k));
+@}
+@end smallexample
+
+@noindent
+Without the call to @code{explicit_bzero}, @var{k} might not need to
+be stored in memory: depending on the ABI, its value could be returned
+from @code{get_key} and passed to @code{use_key} using only CPU
+registers.  @code{explicit_bzero} operates on memory, so the compiler
+has to make a copy of @var{k} in memory for it, and the copy in the
+CPU registers remains intact.  This can occur for any variable whose
+address is only taken in a call to @code{explicit_bzero}, even if it
+might seem ``too large'' to be stored in registers.
+
+@strong{Portability Note:} This function first appeared in OpenBSD 5.5
+and has not been standardized.  @Theglibc{} declares this function in
+@file{string.h}, but on other systems it may be in @file{strings.h}
+instead.
+@end deftypefun
+
 @node strfry
 @section strfry
 
diff --git a/string/Makefile b/string/Makefile
index 9c87419..180ec86 100644
--- a/string/Makefile
+++ b/string/Makefile
@@ -41,13 +41,19 @@  routines	:= strcat strchr strcmp strcoll strcpy strcspn		\
 				     addsep replace)			\
 		   envz basename					\
 		   strcoll_l strxfrm_l string-inlines memrchr		\
-		   xpg-strerror strerror_l
+		   xpg-strerror strerror_l explicit_bzero
+
+# Attention future hackers trying to enable link-time optimization for
+# glibc: this file *must not* be subject to LTO.  It is added separately
+# to 'routines' to document this.  See comments in this file for details.
+routines	+= read_memory
 
 strop-tests	:= memchr memcmp memcpy memmove mempcpy memset memccpy	\
 		   stpcpy stpncpy strcat strchr strcmp strcpy strcspn	\
 		   strlen strncmp strncpy strpbrk strrchr strspn memmem	\
 		   strstr strcasestr strnlen strcasecmp strncasecmp	\
-		   strncat rawmemchr strchrnul bcopy bzero memrchr
+		   strncat rawmemchr strchrnul bcopy bzero memrchr	\
+		   explicit_bzero
 tests		:= tester inl-tester noinl-tester testcopy test-ffs	\
 		   tst-strlen stratcliff tst-svc tst-inlcall		\
 		   bug-strncat1 bug-strspn1 bug-strpbrk1 tst-bswap	\
diff --git a/string/Versions b/string/Versions
index 475c1fd..b5c24f4 100644
--- a/string/Versions
+++ b/string/Versions
@@ -82,4 +82,11 @@  libc {
   }
   GLIBC_2.24 {
   }
+  GLIBC_2.25 {
+    # used by inlines in string2.h
+    __glibc_read_memory;
+
+    # e*
+    explicit_bzero;
+  }
 }
diff --git a/string/bits/string2.h b/string/bits/string2.h
index 8098760..f890585 100644
--- a/string/bits/string2.h
+++ b/string/bits/string2.h
@@ -52,11 +52,23 @@ 
 #define __string2_1bptr_p(__x) \
   ((size_t)(const void *)((__x) + 1) - (size_t)(const void *)(__x) == 1)
 
-/* Set N bytes of S to C.  */
+/* Set N bytes of S to 0.  */
 #if !defined _HAVE_STRING_ARCH_memset
 # define __bzero(s, n) __builtin_memset (s, '\0', n)
 #endif
 
+#ifdef __USE_MISC
+/* As bzero, but the compiler will not delete a call to this
+   function, even if S is dead after the call.  Note: this function
+   has its own implementation file and should not be slurped into
+   string-inlines.o.  */
+__extern_inline void
+explicit_bzero (void *__s, size_t __n)
+{
+  memset (__s, '\0', __n);
+  __glibc_read_memory (__s, __n);
+}
+#endif
 
 #ifndef _HAVE_STRING_ARCH_strchr
 extern void *__rawmemchr (const void *__s, int __c);
diff --git a/string/explicit_bzero.c b/string/explicit_bzero.c
new file mode 100644
index 0000000..a02be4f
--- /dev/null
+++ b/string/explicit_bzero.c
@@ -0,0 +1,30 @@ 
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <features.h>
+#undef __USE_STRING_INLINES
+#define __NO_STRING_INLINES
+#include <string.h>
+
+/* Set LEN bytes of S to 0.  The compiler will not delete a call to
+   this function, even if S is dead after the call.  */
+void
+explicit_bzero (void *s, size_t len)
+{
+  memset (s, '\0', len);
+  __internal_glibc_read_memory (s, len);
+}
diff --git a/string/read_memory.c b/string/read_memory.c
new file mode 100644
index 0000000..c4a5990
--- /dev/null
+++ b/string/read_memory.c
@@ -0,0 +1,41 @@ 
+/* Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+/* This function is an optimization fence.  It doesn't do anything
+   itself, but calls to it prevent calls to explicit_bzero from being
+   optimized away.  In order to achieve this effect, this function
+   must never, under any circumstances, be inlined or subjected to
+   inter-procedural optimization.  string.h declares this function
+   with attributes that, in conjunction with the no-op asm insert, are
+   sufficient to prevent problems in the current (2016) generation of
+   compilers, but *only if* this file is *not* compiled with -flto.
+   At present, this is not an issue since glibc is never compiled with
+   -flto, but should that ever change, this file must be excepted.
+
+   The 'volatile' below is technically not necessary but is included
+   for explicitness.  */
+
+void
+internal_function
+__internal_glibc_read_memory(const void *s, size_t len)
+{
+  asm volatile ("");
+}
+libc_hidden_def (__internal_glibc_read_memory)
+strong_alias (__internal_glibc_read_memory, __glibc_read_memory)
diff --git a/string/string.h b/string/string.h
index 57deaa4..40851b5 100644
--- a/string/string.h
+++ b/string/string.h
@@ -455,6 +455,15 @@  extern void bcopy (const void *__src, void *__dest, size_t __n)
 /* Set N bytes of S to 0.  */
 extern void bzero (void *__s, size_t __n) __THROW __nonnull ((1));
 
+/* As bzero, but the compiler will not delete a call to this
+   function, even if S is dead after the call.  */
+extern void explicit_bzero (void *__s, size_t __n) __THROW __nonnull ((1));
+
+/* Optimization fence, used by bits/string2.h inline version of
+   explicit_bzero.  */
+extern void __glibc_read_memory (const void *__s, size_t __n)
+     __THROW __nonnull ((1)) __attribute_noinline__;
+
 /* Compare N bytes of S1 and S2 (same as memcmp).  */
 extern int bcmp (const void *__s1, const void *__s2, size_t __n)
      __THROW __attribute_pure__ __nonnull ((1, 2));
diff --git a/string/test-explicit_bzero.c b/string/test-explicit_bzero.c
new file mode 100644
index 0000000..5a4543b
--- /dev/null
+++ b/string/test-explicit_bzero.c
@@ -0,0 +1,20 @@ 
+/* Test and measure explicit_bzero.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+#define TEST_EXPLICIT_BZERO
+#define TEST_BZERO
+#include "test-memset.c"
diff --git a/string/test-memset.c b/string/test-memset.c
index fee3bdf..7ca4f20 100644
--- a/string/test-memset.c
+++ b/string/test-memset.c
@@ -19,7 +19,11 @@ 
 
 #define TEST_MAIN
 #ifdef TEST_BZERO
-# define TEST_NAME "bzero"
+# ifdef TEST_EXPLICIT_BZERO
+#  define TEST_NAME "explicit_bzero"
+# else
+#  define TEST_NAME "bzero"
+# endif
 #else
 # ifndef WIDE
 #  define TEST_NAME "memset"
@@ -56,7 +60,11 @@  void builtin_bzero (char *, size_t);
 
 IMPL (simple_bzero, 0)
 IMPL (builtin_bzero, 0)
+#ifdef TEST_EXPLICIT_BZERO
+IMPL (explicit_bzero, 1)
+#else
 IMPL (bzero, 1)
+#endif
 
 void
 simple_bzero (char *s, size_t n)
diff --git a/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index 4d3b0b9..02d4bc6 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1843,6 +1843,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.25 gnu_dev_major F
 GLIBC_2.25 gnu_dev_makedev F
 GLIBC_2.25 gnu_dev_minor F
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 2c2f49e..44dc0d1 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2090,3 +2090,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 8afba47..02a490d 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2001,6 +2001,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index de3bdf4..d2b2800 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -91,6 +91,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0xa0
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 3261b93..59b2591 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1855,6 +1855,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 6465a55..e64f9c6 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2013,6 +2013,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index 4536271..78acf45 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1877,6 +1877,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 287d7a5..ceb1909 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -92,6 +92,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
 GLIBC_2.4 _IO_2_1_stderr_ D 0x98
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index c9229fa..e8d7256 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1969,6 +1969,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 0409791..c2e2ecc 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2090,3 +2090,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index f31653e..705f00b 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1944,6 +1944,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index a56bd99..41d3e5c 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1942,6 +1942,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 44552df..4de5839 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1940,6 +1940,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 8d2a09d..e1d5bec 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1935,6 +1935,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 0443b92..34e83a6 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2131,3 +2131,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index ba9a29a..91a30c8 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1973,6 +1973,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index f19534c..a4ecbc2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1978,6 +1978,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index f8de1ab..277ec26 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2178,3 +2178,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index 6819133..e3dafa5 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -92,6 +92,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
 GLIBC_2.3 _IO_2_1_stderr_ D 0xe0
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 4cd5d85..3ab826d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1973,6 +1973,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 8cdb9df..c4c0a8e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1874,6 +1874,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 69791b4..7a11b8a 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1859,6 +1859,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index fce58a8..13efb9f 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1965,6 +1965,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 16ce739..da6819b 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1903,6 +1903,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index f99c298..0d58dc0 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2097,3 +2097,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index c601ab0..fc55930 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2097,3 +2097,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index f99c298..0d58dc0 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2097,3 +2097,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index 8e6fa57..858a26c 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1854,6 +1854,8 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
 GLIBC_2.3 __ctype_tolower_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 1e12f48..9a45eed 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2097,3 +2097,5 @@  GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __glibc_read_memory F
+GLIBC_2.25 explicit_bzero F